CF981F Round Marriage(二分答案+Hall定理)

二分答案以后就是看是否存在完美匹配。
然而直接建图肯定是gg
我们猜这个hall定理只需要区间满足即可!
如果是一条线的话那直接枚举过去就好了…
但它偏偏是一个环!然后我就gg了,各种瞎搞未果。
正确做法是把这个环拆成链qaq
把所有的点b复制一遍接在后面。
把所有的点b复制一遍接在前面。
对于每一个点a,我们得到一个区间{a-mid,a+mid}
如果a+mid>=L,那么直接覆盖到后面那一段。
如果a-mid<0,那么直接覆盖到前面那一段。
但我们发现这样有一些问题,如果a-mid>=0&&a+mid< L,要把这个区间复制两遍,添加一个a-mid+L,a+mid+L区间。

为了方便我们对每一个a都复制两遍…相应的在前后各接一遍b…
所以就是2n个a,4n个b…
然后按区间那样去做就好了qaq
其实我也不是很明白为啥要拆这么多段qaq,是为了方便处理么qaq,有错误还望dalao指出。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 200010
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,L;ll a[N<<1],b[N<<2];
inline bool jud(int le){
    int mx=-inf,j1=1,j2=1;
    for(int i=1;i<=n*2;++i){
        while(j1<=4*n&&b[j1]<a[i]-le) ++j1;
        while(j2<=4*n&&b[j2]<=a[i]+le) ++j2;
        mx=max(mx,j1-i);
        if(j2-i-1<mx) return 0;
    }return 1;
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();L=read();
    for(int i=1;i<=n;++i) a[i]=read();sort(a+1,a+n+1);
    for(int i=1;i<=n;++i) b[i]=read();sort(b+1,b+n+1);
    for(int i=1;i<=n;++i) a[i]+=L,a[n+i]=a[i]+L;
    for(int i=1;i<=3*n;++i) b[i+n]=b[i]+L;
    int l=0,r=L/2;
    while(l<=r){
        int mid=l+r>>1;
        if(jud(mid)) r=mid-1;
        else l=mid+1;
    }printf("%d\n",r+1);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/icefox_zhx/article/details/80503623