专栏文章

【3】做题心得 - 2025 NOIP #68 - T2【链表】【神人】

题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min08lrk
此快照首次捕获于
2025/12/01 18:26
3 个月前
此快照最后确认于
2025/12/01 18:26
3 个月前
查看原文
你首先考虑把合并变为分裂。然后就可以分治去做,把矩形集合分为两部分。因为问题问的是是否有方案,所以切多少刀都是无所谓的。所以就有一个 n2n^2 的做法是不停递归并判定是否可以切割成功。这个东西如何优化呢?你会发现你不一定每一次都要找到所有分割线,所以就考虑使用链表维护这个东西。然后就成为了一坨答辩,但是代码还是比较好懂的。
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct cast{ int ax,ay,bx,by; }a[N];
int n,lasted,deleted,si[N];
bool cmpAX(int x,int y){ return a[x].ax<a[y].ax; }
bool cmpBX(int x,int y){ return a[x].bx>a[y].bx; }
bool cmpAY(int x,int y){ return a[x].ay<a[y].ay; }
bool cmpBY(int x,int y){ return a[x].by>a[y].by; }
struct mlist{ int nxt[N],prv[N],hd; }axl,ayl,bxl,byl;
void Push(mlist &x,int val){
	x.prv[val]=0;
	x.nxt[val]=x.hd;
	x.prv[x.hd]=val;
	x.hd=val;
}
void Pop(mlist &x,int val){
	x.prv[x.nxt[val]]=x.prv[val];
	x.nxt[x.prv[val]]=x.nxt[val];
	if(x.hd==val) x.hd=x.nxt[val]; 	
}
bool cutter(){
	if(lasted==1) return 1;
	int updated=0;
	int ax=axl.hd,ay=ayl.hd,bx=bxl.hd,by=byl.hd;
	int rx=0     ,ry=0     ,lx=1e9   ,ly=1e9   ;
	for(int i=1;i<=lasted/2;i++){
		rx=max(rx,a[ax].bx); ax=axl.nxt[ax]; if(rx<=a[ax].ax){ updated=1, deleted=i; for(int j=1,p=axl.hd;j<=i;j++,p=axl.nxt[p])si[j]=p; break; }
		ry=max(ry,a[ay].by); ay=ayl.nxt[ay]; if(ry<=a[ay].ay){ updated=1, deleted=i; for(int j=1,p=ayl.hd;j<=i;j++,p=ayl.nxt[p])si[j]=p; break; }
		lx=min(lx,a[bx].ax); bx=bxl.nxt[bx]; if(lx>=a[bx].bx){ updated=1, deleted=i; for(int j=1,p=bxl.hd;j<=i;j++,p=bxl.nxt[p])si[j]=p; break; }
		ly=min(ly,a[by].ay); by=byl.nxt[by]; if(ly>=a[by].by){ updated=1, deleted=i; for(int j=1,p=byl.hd;j<=i;j++,p=byl.nxt[p])si[j]=p; break; }
	}
	if(!updated) return 0;
	lasted-=deleted;
	for(int i=1;i<=deleted;i++)
		Pop(axl,si[i]),
		Pop(bxl,si[i]),
		Pop(ayl,si[i]),
		Pop(byl,si[i]);
	if(!cutter()) return 0;
	axl.hd=0; sort(si+1,si+deleted+1,cmpAX); for(int i=deleted;i>=1;i--) Push(axl,si[i]);
	ayl.hd=0; sort(si+1,si+deleted+1,cmpAY); for(int i=deleted;i>=1;i--) Push(ayl,si[i]);
	bxl.hd=0; sort(si+1,si+deleted+1,cmpBX); for(int i=deleted;i>=1;i--) Push(bxl,si[i]);
	byl.hd=0; sort(si+1,si+deleted+1,cmpBY); for(int i=deleted;i>=1;i--) Push(byl,si[i]);
	lasted=deleted;
	return cutter();
}
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i].ax>>a[i].ay>>a[i].bx>>a[i].by, si[i]=i;
	axl.hd=0; sort(si+1,si+n+1,cmpAX); for(int i=n;i>=1;i--) Push(axl,si[i]);
	ayl.hd=0; sort(si+1,si+n+1,cmpAY); for(int i=n;i>=1;i--) Push(ayl,si[i]);
	bxl.hd=0; sort(si+1,si+n+1,cmpBX); for(int i=n;i>=1;i--) Push(bxl,si[i]);
	byl.hd=0; sort(si+1,si+n+1,cmpBY); for(int i=n;i>=1;i--) Push(byl,si[i]);
	lasted=n;
	cout<<(cutter()?"YES\n":"NO\n");
	return;
}
int main(){
	freopen("kingdom.in","r",stdin);
	freopen("kingdom.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int T;
	cin>>T;
	while(T--) solve();	
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...