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;
}
深深地感到自己的弱小。