Codeforces 981F. Round Marriage
阿新 • • 發佈:2018-07-12
pan com d+ c++ href span long amp its 開始考慮 , 這樣的話同一個黑點既可以在左邊也可以在右邊被匹配到了.
Description
一個長度為 \(L\) 的環上有 \(n\) 個黑點和 \(n\) 個白點 , 你需要把黑點和白點配對 , 使得配對點的最大距離最小 , 最小距離定義為兩點在環上的兩條路徑的最小值.
題面
Solution
二分一個答案 , 把距離小於答案的連邊 , 現在要判斷是否存在完美匹配.
運用 \(Hall\) 定理 , 這題對於所有區間滿足 \(Hall\) 定理 , 就滿足 \(Hall\) 定理.
對於一段白點區間 \([l,r]\) 我們設他們能匹配到的黑點對應的區間是 \([L,R]\) , \(r-l>R-L\) 就不滿足條件.
問題在於本題是個環 , 所以破環成鏈 , 如何考慮最短路徑 ? 只需要把鏈倍長兩次 , 然後從 \(n+1\)
#include<bits/stdc++.h> using namespace std; template<class T>void gi(T &x){ int f;char c; for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1; for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f; } typedef long long ll; const int N=8e5+10; int n,m,p[N];ll a[N],b[N],q[N],L; inline bool check(int mid){ int l=0,r=n,L=1,R=0; for(int i=1;i<=n*3;i++){ while(l<m && b[l+1]<a[i]-mid)l++; while(r<m && b[r+1]<=a[i]+mid)r++; while(L<=R && i-l-1<=q[R])R--; q[++R]=i-l-1,p[R]=i; while(L<=R && i-p[L]>=n)L++; if(L<=R && i-r>q[L])return false; } return true; } int main(){ freopen("pp.in","r",stdin); freopen("pp.out","w",stdout); cin>>n>>L;m=n*4; for(int i=1;i<=n;i++)gi(a[i]); for(int i=1;i<=n;i++)gi(b[i]); sort(a+1,a+n+1),sort(b+1,b+n+1); for(int i=1;i<=n;i++) for(int j=1;j<=3;j++)a[i+j*n]=a[i]+L*j,b[i+j*n]=b[i]+L*j; int l=0,r=L,mid,ans=0; while(l<=r){ mid=(l+r)>>1; if(check(mid))ans=mid,r=mid-1; else l=mid+1; } cout<<ans; return 0; }
Codeforces 981F. Round Marriage