1 条题解
-
0
看懂题意后,很快能想到一种 的做法,直接向一个矩形的左下角的矩形连边,意味着只有左下角的矩形移走后,它才能移动,因为这是一种单向的关系,所以一定不会有环一类的东西出现,但可能是 DAG,所以这时跑一个拓扑就好了。
那再来考虑 的情况,这种情况下,我们不能直接去连边,那就直接不连边了,因为我们只需要知道这个点可以到达的节点,把那个节点以相同的方式删除,因为每个点只会被删除一次,所以时间复杂度还是 的。那现在就是怎样去找一个挡住这个节点的点。这里借鉴了沉石鱼惊旋老师的解法,可以用线段树维护每一个矩阵的左下角的坐标,以横坐标为下标,纵坐标为值域,然后查询是否可以移走这个节点时,只需要在线段树上查下标小于它的答案,如果答案大于了它的纵坐标,那它现在就是可移走的。这里的总时间复杂度是 的。
然后因为方便,这里的拓扑用 dfs 实现较短,只需要判断当前节点是否可以被删,如果不行,就先把自己先删除,防止自环,因为是查横坐标小于自己的节点,所以不会有影响,然后查挡住它的节点,直到把挡住它的点删完,然后输出当前节点,回溯即可。还是比较简单的。
#include<bits/stdc++.h> #define int long long #define pl p<<1 #define pr p<<1|1 #define mst(x,y) memset(x,y,sizeof x) #define D(x) cout<<#x<<": "<<x<<endl; #define DE(x) cout<<#x<<": "<<x<<" "; #define MAXSIZE 1<<21 using namespace std; constexpr int N=200000+10,mod=1000000007,inf=0x3f3f3f3f3f3f3f3f; array<int,2> tr[N<<3]; inline void pushup(int p){ tr[p]=min(tr[pl],tr[pr]); } inline void build(int p,int L,int R){ tr[p]={inf,-1}; if(L==R) return; int mid=(L+R)>>1; build(pl,L,mid); build(pr,mid+1,R); pushup(p); } inline void update(int p,int L,int R,int x,array<int,2> k){ if(L==R){ tr[p]=k; return; } int mid=(L+R)>>1; if(x<=mid) update(pl,L,mid,x,k); else update(pr,mid+1,R,x,k); pushup(p); } inline array<int,2> query(int p,int L,int R,int l,int r){ if(l<=L&&R<=r) return tr[p]; int mid=(L+R)>>1; array<int,2> res={inf,-1}; if(l<=mid) res=min(res,query(pl,L,mid,l,r)); if(r>mid) res=min(res,query(pr,mid+1,R,l,r)); return res; } struct node{ int x,y; }a[N],b[N]; int T,M,n; bool del[N],vis[N]; inline void dfs(int x){ if(del[x]) return; if(!vis[x]){ update(1,1,n*2,a[x].x,{inf,-1}); vis[x]=1; } auto tmp=query(1,1,n*2,1,b[x].x); if(tmp[0]>=b[x].y){ del[x]=1; cout<<x<<" "; return; } dfs(tmp[1]); dfs(x); } signed main(){ cin>>T>>M; while(T--){ cin>>n; for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y>>b[i].x>>b[i].y; if(M==1){ memset(del,0,sizeof del); memset(vis,0,sizeof vis); build(1,1,n*2); for(int i=1;i<=n;i++) update(1,1,n*2,a[i].x,{a[i].y,i}); for(int i=1;i<=n;i++) dfs(i); }else{ build(1,1,n*2); for(int i=1;i<=n;i++) update(1,1,n*2,a[i].x,{a[i].y,i}); for(int i=1;i<=n;i++){ update(1,1,n*2,a[i].x,{inf,-1}); cout<<(query(1,1,n*2,1,b[i].x)[0]>=b[i].y); } } puts(""); } return 0; }
- 1
信息
- ID
- 1570
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 18
- 已通过
- 3
- 上传者