zoukankan      html  css  js  c++  java
  • 二分图hall定理应用+二分+双指针——cf981F(好题)

    /* 
    二分答案,判mid是否合法 
    如何判断:如果是在直线上,那么遍历匹配即可
    现在在环上,即既可以向前匹配也可以向后匹配,那么将环拆开,扩展成三倍
    
    显然a和b的匹配边是不可能交叉的,因为交叉必定没有不交叉优 
    hall定理:二分图两个点集A,B,连续一段A的点对应连续一段B的点的 充要条件是 这些点对的匹配边之间不交叉
    重要推论:二部图G中的两部分顶点组成的集合分别为X,Y, 若|X|=|Y|,
              且G中有一组无公共端点的边,一端恰好组成X中的点,一端恰好组成Y中的点,则称二部图G中存在完美匹配 
    
    有了这个定理,就可以用在判定上:a的点集对应b点集的连续一段,即b的n个点也是连续的,因为之前已经确定匹配边不交叉 
    先求出a[1]的范围[a[1]-mid,a[1]+mid]对应的能控制的b数组的范围[l1,r1]
    那么a[2]的控制范围要和[l1+1,r1+1]交叉得到[l2,r2] 
    那么a[3]的控制范围要和[l2+1,r2+1]交叉得到[l3,r3] 
    ...依次类推

    可以这个区间长度只会减小不会变大
    */ #include<bits/stdc++.h> using namespace std; #define maxn 200005 long long n,L,a[maxn],b[maxn<<2],c[maxn],m; int judge(int mid){//a[i]的控制区间是[a[i]-mid,a[i]+mid] int l=1,r=m; for(int i=1;i<=n;i++){ while(a[i]-mid>b[l]) ++l; while(a[i]+mid<b[r]) --r; if(l>r)return 0; ++l,++r; } return 1; } int main(){ cin>>n>>L; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=n;i++)cin>>c[i]; sort(c+1,c+1+n);sort(a+1,a+1+n); for(int i=1;i<=n;i++)b[i]=c[i]-L; for(int i=1;i<=n;i++)b[i+n]=c[i]; for(int i=1;i<=n;i++)b[i+2*n]=c[i]+L; m=3*n; int l=0,r=L,ans,mid; while(l<=r){ mid=l+r>>1; if(judge(mid)) ans=mid,r=mid-1; else l=mid+1; } cout<<ans<<' '; }
  • 相关阅读:
    微软消息队列
    使用Memcached Provider客户端的increment()||decrement()操作小结
    SQL While And Sql Array
    好管理是成功的99%
    Javascript图片无缝滚动
    javascript数组复习
    前端面试题--js切换td中的值
    推荐使用:易企在线客服升级版
    drupal中根据不同的内容类型节点显示不同的样式
    defer和async(原生js学习)转
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11176246.html
Copyright © 2011-2022 走看看