0
点赞
收藏
分享

微信扫一扫

NOIP2021T1 的 O(10n) 解法

攻城狮Chova 2022-03-31 阅读 51

UPD:洛谷炸了,代码没了。

UPD:原代码作者表示,他会再写一份。

UPD:发文助手表示文章质量不佳,放一个汉堡肉镇楼

#include<bits/stdc++.h>
using namespace std;
int n,K;
const int inf=1e9+5;
const int maxn=2e6+5;
int idt=0;
int data[maxn],dt;
int ID[maxn][2];
int suf[maxn][2];
int tmp[maxn];
int d[maxn];
int L[maxn],D[maxn],R[maxn],U[maxn];
bool vis[maxn];
namespace Vsat{	
	struct Edge{
		int u,v,nxt;
	}e[maxn];
	int h[maxn],cnt;
	void add(int u,int v){ 
//		cout<<u<<" "<<v<<endl;
		e[++cnt].u=u;	
		e[cnt].v=v;
		e[cnt].nxt=h[u];
		h[u]=cnt;
	}
	int dfn[maxn],low[maxn],sccno[maxn],tp[maxn],tot=0;
	int scc_cnt=0;
	stack<int>S;	
	void tarjan(int u){
		dfn[u]=low[u]=++tot;
		S.push(u);
		for(int i=h[u];i;i=e[i].nxt){
			int v=e[i].v;
			if(!dfn[v]){
				tarjan(v);
				low[u]=min(low[u],low[v]);
			}	
			else if(!sccno[v]){	
				low[u]=min(low[u],dfn[v]);
			} 
		}
		if(low[u]==dfn[u]){
			scc_cnt++; 
			while(1){
				int x=S.top();
				S.pop();
				tp[scc_cnt]=x;
				sccno[x]=scc_cnt;
				if(x==u)break;
			} 
		}
	}
	bool sat[maxn];
	void SAT_solver(int n){
	 	for(int i=1;i<=n;i++){
			if(!dfn[i])tarjan(i);
		}
		bool f=0;
		for(int i=1;i<=idt;i++){ 
			if(sccno[ID[i][1]]<=sccno[ID[i][0]])sat[ID[i][1]]=1;
			else sat[ID[i][0]]=1;
		} 
	}
}
int op[maxn][5],opx[maxn],opy[maxn];
void hack(int x,int y,int t){
	opx[t]=x;
	opy[t]=y;
	op[0][t]=0;
	for(int i=1;i<=n;i++){
		if(vis[i])continue;
		if(L[i]<=x&&x<=R[i]&&D[i]<=y&&y<=U[i]){
			vis[i]=1;
			op[++op[0][t]][t]=i;
		}
	}
} 
void cancel_hack(int t){
	for(int i=1;i<=op[0][t];i++)vis[op[i][t]]=0;
}
bool sat(){
	for(int i=1;i<=n;i++){
		if(!vis[i])return 0;
	}
	return 1;
}
void dfs(int k,bool tag){ 
	if(k==K+1){
		if(sat()){
			for(int i=1;i<=K;i++){
				printf("%d %d\n",opx[i],opy[i]);
			}
			exit(0);
		}
		return ;
	}
	int Lx,Dx,Rx,Ux;
	Lx=Dx=0;
	Rx=Ux=inf;
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			Lx=max(Lx,L[i]);
			Dx=max(Dx,D[i]);
			Rx=min(Rx,R[i]);
			Ux=min(Ux,U[i]);	
		}
	}
	hack(Lx,Dx,k);dfs(k+1,tag);cancel_hack(k);
	hack(Lx,Ux,k);dfs(k+1,tag);cancel_hack(k);
	hack(Rx,Dx,k);dfs(k+1,tag);cancel_hack(k);
	hack(Rx,Ux,k);dfs(k+1,tag);cancel_hack(k);
} 
struct Seg{
	int l,r,id;
};
bool cmp1(Seg a,Seg b){
	return a.r<b.r;
}
bool cmp2(Seg a,Seg b){
	return a.l>b.l;
}
vector<Seg>G[5]; 
int node_cnt;
int main(){
//	freopen("04-14.in","r",stdin);
	scanf("%d%d",&n,&K);
	int Lx,Dx,Rx,Ux;
	Lx=Dx=0;
	Rx=Ux=inf;
	for(int i=1;i<=n;i++){
		scanf("%d%d%d%d",&L[i],&D[i],&R[i],&U[i]);
		Lx=max(Lx,L[i]);
		Dx=max(Dx,D[i]);
		Rx=min(Rx,R[i]);
		Ux=min(Ux,U[i]);
	}
	if(K<=3){
		dfs(1,1);
	}
	else{
		dfs(1,1);    
		for(int i=1;i<=n;i++){
			int cnt=0; 
			int X1=-1,X2=-1,Y1=-1,Y2=-1; 
			if(L[i]<=Lx&&Lx<=R[i])cnt++,X1=1;
			if(L[i]<=Rx&&Rx<=R[i])cnt++,X2=2;
			if(D[i]<=Dx&&Dx<=U[i])cnt++,Y1=3;
			if(D[i]<=Ux&&Ux<=U[i])cnt++,Y2=4;  
			if(cnt>2||cnt==0)continue;
			if(X1>0)G[X1].push_back((Seg){max(0,D[i]),min(inf,U[i]),++idt}),ID[idt][1]=++node_cnt,ID[idt][0]=++node_cnt;
			if(X2>0)G[X2].push_back((Seg){max(0,D[i]),min(inf,U[i]),++idt}),ID[idt][1]=++node_cnt,ID[idt][0]=++node_cnt;
			if(Y1>0)G[Y1].push_back((Seg){max(0,L[i]),min(inf,R[i]),++idt}),ID[idt][1]=++node_cnt,ID[idt][0]=++node_cnt; 
			if(Y2>0)G[Y2].push_back((Seg){max(0,L[i]),min(inf,R[i]),++idt}),ID[idt][1]=++node_cnt,ID[idt][0]=++node_cnt; 
			if(cnt==2){ 
				Vsat::add(ID[idt][0],ID[idt-1][1]);
				Vsat::add(ID[idt-1][0],ID[idt][1]);
			}
			else{ 
//				cout<<i<<endl;  
				Vsat::add(ID[idt][0],ID[idt][1]);
			}
		}
		for(int i=1;i<=4;i++){
//			cout<<i<<" "<<G[i].size()0<<endl;
			sort(G[i].begin(),G[i].end(),cmp1);
			for(int j=0;j<G[i].size();j++){
				tmp[j]=G[i][j].r;
//				cout<<G[i][j].r<<endl;
				suf[j][0]=++node_cnt; 
				if(j)Vsat::add(suf[j][0],suf[j-1][0]);
				int now=G[i][j].id;
				Vsat::add(suf[j][0],ID[now][0]);
			}
			for(int j=1;j<G[i].size();j++){ 
				int now=G[i][j].id;
				int lst=lower_bound(tmp,tmp+j+1,G[i][j].l)-tmp; 
				if(lst)Vsat::add(ID[now][1],suf[lst-1][0]); 
//				for(int k=0;k<lst;k++){
//					Vsat::add(ID[now][1],ID[G[i][k].id][0]);
//				}
			}	 
			sort(G[i].begin(),G[i].end(),cmp2);
			for(int j=0;j<G[i].size();j++){
				tmp[j]=-G[i][j].l;
				suf[j][1]=++node_cnt; 
				if(j)Vsat::add(suf[j][1],suf[j-1][1]);
				int now=G[i][j].id;
				Vsat::add(suf[j][1],ID[now][0]);
			}
			for(int j=1;j<G[i].size();j++){ 
				int now=G[i][j].id;
				int lst=lower_bound(tmp,tmp+j+1,-G[i][j].r)-tmp; 
				if(lst)Vsat::add(ID[now][1],suf[lst-1][1]);  
//				for(int k=0;k<lst;k++){
//					Vsat::add(ID[now][1],ID[G[i][k].id][0]);
//				} 
			}	 
		}
		Vsat::SAT_solver(node_cnt);
//		for(int i=1;i<=node_cnt;i++)cout<<Vsat::sat[i]<<endl; 
		for(int i=1;i<=4;i++){
		 	int aL=0,aR=inf;
		 	for(int j=0;j<G[i].size();j++){
			 	int now=G[i][j].id;
//			 	cout<<now<<"-p"<<G[i][j].idx<<" "<<ID[now][1]<<endl;
			 	if(!Vsat::sat[ID[now][1]])continue;
//			 	cout<<G[i][j].idx<<"!"<<endl;
				aL=max(aL,G[i][j].l);
				aR=min(aR,G[i][j].r); 
			} 
			if(i==1)printf("%d %d\n",Lx,aL);
			if(i==2)printf("%d %d\n",Rx,aL);
			if(i==3)printf("%d %d\n",aL,Dx);
			if(i==4)printf("%d %d\n",aL,Ux);
		}
	}
	return 0;
}
举报

相关推荐

L1-009 N个数求和 (20 分) Java解法

0 条评论