正题
把a排序后,最优的方案就是找到一个断点,使得左边x+y<m,且右边x+y>=m,然后左右分别首尾配对使得最大值最小。
具体证明可以自己想想不合法的方案,发现都可以转化为一种等价或更优的合法方案。
然后怎么找这个断点呢?
可以发现左右的最大值都是随着断点的右移而增大的。
那么要找的就是最小合法断点,二分即可,判断可不可行直接看右边是否有x+y<m的对
或者找左边有没有x+y>=m的对即可。
可以简单证明如果一边不合法,另一边必定都合法。
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int n,a[N],m;
bool check(int x){
for(int i=x*2+1;i<=2*n;i++) if(a[i]+a[2*n-i+2*x+1]<m) return false;
return true;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=2*n;i++) scanf("%d",&a[i]);
sort(a+1,a+1+2*n);
int l=0,r=n,ans=0;
while(l<=r){
int mid=(l+r)/2;
if(check(mid)) r=(ans=mid)-1;
else l=mid+1;
}
int mmax=0;
for(int i=1;i<=ans;i++) mmax=max(mmax,a[i]+a[2*ans-i+1]);
for(int i=2*ans+1;i<=2*n;i++) mmax=max(mmax,a[i]+a[2*n-i+2*ans+1]-m);
printf("%d\n",mmax);
}
本文探讨了通过排序和二分查找解决特定配对问题的算法优化方法。介绍了一种寻找断点的策略,使左侧x+y<m,右侧x+y>=m,从而实现最小化最大值的目标。通过证明不合法方案的转化,阐述了算法的正确性和高效性。
571

被折叠的 条评论
为什么被折叠?



