Time Limits: 2000 ms Memory Limits: 1048576 KB
Description
Snuke 喜欢旗子.
Snuke 正在将N 个旗子摆在一条线上.
第i 个旗子可以被放在位置xi 或yi 上.
Snuke 认为两个旗子间的最小距离越大越好. 请你求出最大值.
Input
N
x1 y1
…
xN yN
Output
输出一行一个整数表示答案.
Sample Input
输入1:
3
1 3
2 5
1 9
输入2:
5
2 2
2 2
2 2
2 2
2 2
输入3:
22
93 6440
78 6647
862 11
8306 9689
798 99
801 521
188 206
6079 971
4559 209
50 94
92 6270
5403 560
803 83
1855 99
42 504
75 484
629 11
92 122
3359 37
28 16
648 14
11 269
Sample Output
输出1:
4
输出2:
0
输出3:
17
Data Constraint
对于30% 的数据, N <=18;
对于60% 的数据, N <=1000;
对于100% 的数据, 1 <= N <= 10^4; 1 <= xi, yi <= 10^9.
2-set的连边:如果选了一个点后不能选另一个点,那么就在那个点对应的另一个点连一条单向边
考虑2-set
一个比较显然的思路是我们可以二分答案,然后用2-set判断可行性
但是这样会超时
我们可以先把所有的点排序,然后就可以比较快的连边了,我们还可以事先搞一个较小的上界,也就是对两个点对中最远的点对的距离的最小值
但是这只是一个水法
我们有一个很优秀的算法
我们可以对a,b分别排序,然后建两颗线段树,然后对于一个点,它可以连的边就是线段树中对应的连续的一段点,那么我们不妨连到那个子树的根,对线段树我们从上往下连一些单向边就好了
这样我们就可以用n log n级别的点数和边树完成对图的构造了,然后我们对这个图跑一下2-set就好了
#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=2e4+5,cs=3e7+5;
struct P{
int x,y;
}a[maxn];
int fi[maxn*2],ne[cs*2],dui[cs*2],qc[cs*2];
bool bb[maxn*2],bz[maxn*2];
int dfn[maxn],low[maxn],st[maxn],cc[maxn];
int i,j,k,l,r,n,m,x,y,ma,mid,nc,cq,tp,now;
int cmp(P x,P y){
return x.xvoid add(int x,int y){
if (fi[x]==0) fi[x]=++now; else ne[qc[x]]=++now;
qc[x]=now; dui[now]=y;
}
void ge_bian(){
fo(i,1,now) ne[i]=0;
now=0;
memset(fi,0,sizeof(fi));
fo(i,1,2*n){
j=i-1;
while (j>0 && a[i].x-a[j].xif (abs(a[i].y-a[j].y)!=n){
if (a[j].y>n) add(a[i].y,a[j].y-n); else add(a[i].y,a[j].y+n);
}
j--;
}
j=i+1;
while (j<=2*n && a[j].x-a[i].xif (abs(a[i].y-a[j].y)!=n){
if (a[j].y>n) add(a[i].y,a[j].y-n); else add(a[i].y,a[j].y+n);
}
j++;
}
}
}
void tarjan(int x){
dfn[x]=low[x]=++cq; bz[x]=true; bb[x]=true;
st[++tp]=x;
int i=fi[x];
while (i){
if (bz[dui[i]]==false){
tarjan(dui[i]);
low[x]=min(low[x],low[dui[i]]);
} else if (bb[dui[i]]==true) low[x]=min(low[x],low[dui[i]]);
i=ne[i];
}
if (dfn[x]==low[x]){
nc++;
while (true){
cc[st[tp]]=nc;
bb[st[tp]]=false;
tp--;
if (st[tp+1]==x) break;
}
}
}
bool check(){
memset(bz,false,sizeof(bz));
memset(bb,false,sizeof(bb));
memset(cc,0,sizeof(cc));
nc=cq=tp=0;
fo(i,1,2*n)
if (bz[i]==false) tarjan(i);
fo(i,1,n) if (cc[i]==cc[i+n]) return false;
return true;
}
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&n);
ma=0x7fffffff;
fo(i,1,n){
scanf("%d%d",&x,&y);
a[i].x=x; a[i].y=i;
a[i+n].x=y; a[i+n].y=i+n;
fo(j,1,i-1){
x=max(abs(a[i].x-a[j].x),abs(a[i].x-a[j+n].x));
y=max(abs(a[i+n].x-a[j].x),abs(a[i+n].x-a[j+n].x));
ma=min(ma,max(x,y));
}
}
sort(a+1,a+n*2+1,cmp);
fo(i,1,2*n) dui[a[i].y]=i;
l=1;
r=ma;
while (l2;
ge_bian();
if (check()) l=mid+1; else r=mid;
}
mid=l;
ge_bian(); if (check()==false) l--;
printf("%d\n",l);
return 0;
}