AT2336 [ARC069D] Flags

先赞一波\(AtCoder\):精美的版面设计、优良的评测速度让人舒适(除了看不了数据以外其他都好)。

这题思路显然:二分答案+\(2-sat\)判定+线段树优化建图。

细节比较多,注意离散化的时候不要\(unique\)掉了。

注意有\(6n\)个点,有\(12n+8nlogn\)条边,数组要开够。

时间复杂度:\(\Theta(nlog^2n)\),空间复杂度:\(\Theta(nlogn)\)

代码如下,仅供参考:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5+10;
int n,a[maxn],b[maxn],xv[maxn],vis[maxn];
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
int beg[maxn],nex[20*maxn],to[20*maxn],e;
inline void add(int x,int y){
	e++;nex[e]=beg[x];
	beg[x]=e;to[e]=y;
}
int ri[maxn],ro[maxn],cnt;
inline void buildi(int h,int l,int r){
	if(l==r)return void(ri[h]=l+2*n);
	ri[h]=++cnt;
	int mid=(l+r)>>1;
	buildi(h<<1,l,mid);
	buildi(h<<1|1,mid+1,r);
	add(ri[h],ri[h<<1]);
	add(ri[h],ri[h<<1|1]);
}
inline void buildo(int h,int l,int r){
	if(l==r)return void(ro[h]=l);
	ro[h]=++cnt;
	int mid=(l+r)>>1;
	buildo(h<<1,l,mid);
	buildo(h<<1|1,mid+1,r);
	add(ro[h<<1],ro[h]);
	add(ro[h<<1|1],ro[h]);
}
inline void updatei(int h,int l,int r,int x,int y,int nod){
	if(l>y||r<x||x>y)return;
	if(l>=x&&r<=y){add(nod,ri[h]);return;}
	int mid=(l+r)>>1;
	updatei(h<<1,l,mid,x,y,nod);
	updatei(h<<1|1,mid+1,r,x,y,nod);
}
inline void updateo(int h,int l,int r,int x,int y,int nod){
	if(l>y||r<x||x>y)return;
	if(l>=x&&r<=y){add(ro[h],nod+2*n);return;}
	int mid=(l+r)>>1;
	updateo(h<<1,l,mid,x,y,nod);
	updateo(h<<1|1,mid+1,r,x,y,nod);
}
int dfn[maxn],low[maxn],ins[maxn],ti;
stack<int>st;int col[maxn],scc;
inline void tarjan(int x){
	dfn[x]=low[x]=++ti;
	ins[x]=1;st.push(x);
	for(int i=beg[x];i;i=nex[i]){
		int t=to[i];
		if(!dfn[t]){
			tarjan(t);
			low[x]=min(low[x],low[t]);
		}else if(ins[t])
			low[x]=min(low[x],dfn[t]);
	}
	if(low[x]==dfn[x]){
		col[x]=++scc;
		ins[x]=0;
		while(st.top()!=x){
			int t=st.top();
			st.pop();
			col[t]=scc;
			ins[t]=0;
		}
		st.pop();
	}
}
inline int check(int d){
	cnt=4*n;scc=ti=e=0;
	memset(beg,0,sizeof(beg));
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	for(int i=1;i<=n;i++){
		add(a[i],2*n+b[i]);add(a[i]+2*n,b[i]);
		add(b[i],2*n+a[i]);add(b[i]+2*n,a[i]);
	}
	buildi(1,1,2*n);
	buildo(1,1,2*n);
	for(int i=1;i<=n;i++){
		int lb=lower_bound(xv+1,xv+1+2*n,xv[a[i]]-d+1)-xv;
		int rb=lower_bound(xv+1,xv+1+2*n,xv[a[i]]+d)-xv-1;
		updatei(1,1,2*n,lb,a[i]-1,a[i]);
		updatei(1,1,2*n,a[i]+1,rb,a[i]);
		updateo(1,1,2*n,lb,a[i]-1,a[i]);
		updateo(1,1,2*n,a[i]+1,rb,a[i]);
	}
	for(int i=1;i<=n;i++){
		int lb=lower_bound(xv+1,xv+1+2*n,xv[b[i]]-d+1)-xv;
		int rb=lower_bound(xv+1,xv+1+2*n,xv[b[i]]+d)-xv-1;
		updatei(1,1,2*n,lb,b[i]-1,b[i]);
		updatei(1,1,2*n,b[i]+1,rb,b[i]);
		updateo(1,1,2*n,lb,b[i]-1,b[i]);
		updateo(1,1,2*n,b[i]+1,rb,b[i]);
	}
	for(int i=1;i<=cnt;i++)
		if(!dfn[i])tarjan(i);
	for(int i=1;i<=2*n;i++)
		if(col[i]==col[i+2*n])return 0;
	return 1;
}
signed main(){
	n=read();
	for(int i=1;i<=n;i++){
		a[i]=read();xv[i*2-1]=a[i];
		b[i]=read();xv[i*2]=b[i]; 
	}
	sort(xv+1,xv+1+2*n);
	for(int i=1;i<=2*n;i++)
		vis[i]=i;
	for(int i=1;i<=n;i++){
		a[i]=vis[lower_bound(xv+1,xv+1+2*n,a[i])-xv]++;
		b[i]=vis[lower_bound(xv+1,xv+1+2*n,b[i])-xv]++;
	}
	//for(int i=1;i<=n;i++)
	//	printf("%lld %lld\n",a[i],b[i]);
	int l=0,r=1e9,ans=0;
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(mid))ans=mid,l=mid+1;
		else r=mid-1;
	}
	printf("%lld\n",ans);
	return 0;
}

深深地感到自己的弱小。

posted @ 2020-11-25 22:40  syzf2222  阅读(115)  评论(0编辑  收藏  举报