1 条题解

  • 0
    @ 2026-5-5 10:37:39

    看懂题意后,很快能想到一种 O(n2)O(n^2) 的做法,直接向一个矩形的左下角的矩形连边,意味着只有左下角的矩形移走后,它才能移动,因为这是一种单向的关系,所以一定不会有环一类的东西出现,但可能是 DAG,所以这时跑一个拓扑就好了。

    那再来考虑 n100000n\le100000 的情况,这种情况下,我们不能直接去连边,那就直接不连边了,因为我们只需要知道这个点可以到达的节点,把那个节点以相同的方式删除,因为每个点只会被删除一次,所以时间复杂度还是 O(n)O(n) 的。那现在就是怎样去找一个挡住这个节点的点。这里借鉴了沉石鱼惊旋老师的解法,可以用线段树维护每一个矩阵的左下角的坐标,以横坐标为下标,纵坐标为值域,然后查询是否可以移走这个节点时,只需要在线段树上查下标小于它的答案,如果答案大于了它的纵坐标,那它现在就是可移走的。这里的总时间复杂度是 O(nlogn)O(n\log n) 的。

    然后因为方便,这里的拓扑用 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
    上传者