题意
一些旗子,在数轴上有两个可以放置的位置,最大化两个旗子之间的最小距离
正解
二选一,考虑2-SAT
考虑
O
(
n
2
)
O(n^2)
O(n2)连边的优化:线段树优化建图优化至
O
(
n
log
n
)
O(n\log n)
O(nlogn)
二分答案
对于每一个长度
l
l
l,对于每一个点,位置记为
p
p
p,在
[
p
−
l
,
p
+
l
]
[p-l,p+l]
[p−l,p+l]中不能有其他的点
线段树建图,然后跑2-SAT判是否有解即可
#include<bits/stdc++.h>
using namespace std;
#define in Read()
int in{
int i=0,f=1;char ch=0;
while (!isdigit(ch) && ch!='-') ch=getchar();
if (ch=='-') ch=getchar(),f=-1;
while (isdigit(ch))
i=(i<<1)+(i<<3)+ch-48, ch=getchar();
return i*f;
}
const int N=1e6+5;
int n,len;
int tot,first[N],nxt[N],aim[N];
int idx[N],cnt,dfn[N],low[N],blk[N],sz,ord;
stack<int> sta;
bool exi[N];
struct Flag{
int pos,id;
friend bool operator < (const Flag a,const Flag b){
return a.pos<b.pos;
}
Flag(int pos=0):pos(pos){}
}flag[N];
int opp(int x){
return x>n?x-n:x+n;
}
void ljb(int u,int v){
++tot;
nxt[tot]=first[u];
first[u]=tot;
aim[tot]=v;
return;
}
void build(int p,int l,int r){
idx[p]=++cnt;
if(l==r){
ljb(idx[p],opp(flag[l].id));
return;
}
int mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
ljb(idx[p],idx[p<<1]);
ljb(idx[p],idx[p<<1|1]);
return;
}
void link(int p,int l,int r,int L,int R,int pnt){
if(R<L) return;
if(l==L&&r==R){
ljb(pnt,idx[p]);
return;
}
int mid=l+r>>1;
if(R<=mid) return link(p<<1,l,mid,L,R,pnt);
else if(L>mid) return link(p<<1|1,mid+1,r,L,R,pnt);
else return link(p<<1,l,mid,L,mid,pnt),link(p<<1|1,mid+1,r,mid+1,R,pnt);
}
void tarjan(int u){
dfn[u]=low[u]=++ord;
sta.push(u);
exi[u]=true;
for(int e=first[u];e;e=nxt[e]){
int v=aim[e];
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else{
if(exi[v])
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
++sz;
while(sta.top()!=u){
int v=sta.top();
sta.pop();
exi[v]=false;
blk[v]=sz;
}
sta.pop();
exi[u]=false;
blk[u]=sz;
}
return;
}
bool check(int lim){
cnt=n<<1;
sz=ord=0;
tot=0;
memset(idx,0,sizeof idx);
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(blk,0,sizeof blk);
memset(nxt,0,sizeof nxt);
memset(aim,0,sizeof aim);
memset(first,0,sizeof first);
build(1,1,n<<1);
for(int i=1;i<=(n<<1);++i){
int l=upper_bound(flag+1,flag+(n<<1)+1,Flag(flag[i].pos-lim))-flag;
int r=upper_bound(flag+1,flag+(n<<1)+1,Flag(flag[i].pos+lim-1))-flag-1;
// pay attention to the endpoints.
link(1,1,n<<1,l,i-1,flag[i].id);
link(1,1,n<<1,i+1,r,flag[i].id);
}
for(int i=1;i<=(n<<1);++i)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;++i)
if(blk[i]==blk[i+n]) return false;
return true;
}
int main(){
n=in;
for(int i=1;i<=n;++i){
flag[i].pos=in;
flag[i].id=i;
flag[i+n].pos=in;
flag[i+n].id=i+n;
}
sort(flag+1,flag+(n<<1)+1);
int l=0,r=flag[n<<1].pos-flag[1].pos+1,ans;
while(l<=r){
int mid=l+r>>1;
if(check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}