题解:二分答案+线段树优化连边+2-SAT。
二分答案mid,可以发现每个点要向连续的一段区间内的点连边,离散化后线段树优化连边即可。然后跑2-SAT判定是否有解。
#include
#include
#include
#include
#include
using namespace std;
const int N=10005,M=1000005,K=60005;
int n,l,r,mid,ans,cnt,x[N],y[N],h[N*2],id[N*2],head[K],to[M],nxt[M];
int idx,tot,dfn[K],low[K],scc[K],stk[K];
map<int,int> mp;
void adde(int u,int v){
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
namespace sgt{
int root,tot,ch[K][2];
void init(){
root=tot=0;
}
void build(int &o,int l,int r){
if(l==r){
o=id[l];
return;
}
o=++tot;
int mid=(l+r)/2;
build(ch[o][0],l,mid);
build(ch[o][1],mid+1,r);
adde(o,ch[o][0]);
adde(o,ch[o][1]);
}
void update(int o,int l,int r,int L,int R,int x){
if(L<=l&&R>=r){
adde(x,o);
return;
}
int mid=(l+r)/2;
if(L<=mid){
update(ch[o][0],l,mid,L,R,x);
}
if(R>mid){
update(ch[o][1],mid+1,r,L,R,x);
}
}
}
void tarjan(int u){
dfn[u]=low[u]=++idx;
stk[++stk[0]]=u;
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(!scc[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
tot++;
do{
scc[stk[stk[0]]]=tot;
}while(stk[stk[0]--]!=u);
}
}
void init(){
cnt=idx=tot=0;
memset(head,0,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(scc,0,sizeof(scc));
sgt::init();
}
bool check(){
init();
sgt::tot=2*n;
sgt::build(sgt::root,1,h[0]);
for(int i=1;i<=n;i++){
int l=lower_bound(h+1,h+h[0]+1,h[x[i]]-mid+1)-h;
int r=upper_bound(h+1,h+h[0]+1,h[x[i]]+mid-1)-h-1;
if(l<=r){
if(l1,h[0],l,x[i]-1,i+n);
}
if(x[i]1,h[0],x[i]+1,r,i+n);
}
}
l=lower_bound(h+1,h+h[0]+1,h[y[i]]-mid+1)-h;
r=upper_bound(h+1,h+h[0]+1,h[y[i]]+mid-1)-h-1;
if(l<=r){
if(l1,h[0],l,y[i]-1,i);
}
if(y[i]1,h[0],y[i]+1,r,i);
}
}
}
for(int i=1;i<=sgt::tot;i++){
if(!dfn[i]){
tarjan(i);
}
}
for(int i=1;i<=n;i++){
if(scc[i]==scc[i+n]){
return false;
}
}
return true;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&x[i],&y[i]);
h[++h[0]]=x[i];
h[++h[0]]=y[i];
}
sort(h+1,h+h[0]+1);
for(int i=1;i<=h[0];i++){
if(h[i]!=h[i-1]){
mp[h[i]]=i;
}
}
for(int i=1;i<=n;i++){
int tmp=x[i];
x[i]=mp[tmp];
mp[tmp]++;
tmp=y[i];
y[i]=mp[tmp];
mp[tmp]++;
id[x[i]]=i;
id[y[i]]=i+n;
}
l=0,r=1e9;
while(l<=r){
mid=(l+r)/2;
if(check()){
ans=mid;
l=mid+1;
}else{
r=mid-1;
}
}
printf("%d\n",ans);
return 0;
}