zoukankan      html  css  js  c++  java
  • AtCoder AGC032E Modulo Pairing (二分、贪心与结论)

    题目链接

    https://atcoder.jp/contests/agc032/tasks/agc032_e

    题解

    猜结论好题。
    结论是: 按(a_i)从小到大排序之后,一定存在一种最优解,使得以某个位置为界,两边分别首尾匹配,且满足左边的每一对的和都(<M), 右边每一对的和都(ge M).
    证明不难,可参考官方题解,此处不再赘述。
    然后显然可以枚举这个临界点,然后(O(n))暴力计算答案,时间复杂度(O(n^2)).
    考虑优化: 在我们配对的时候,当临界点右移,左右两侧的每一对和都会变大。
    于是我们只需找到最小的合法临界点,即是最优解。
    二分找即可,时间复杂度(O(nlog n)).

    代码

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cassert>
    #include<algorithm>
    using namespace std;
    
    const int N = 2e5;
    int a[N+3];
    int n,m;
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1; i<=n+n; i++) scanf("%d",&a[i]);
    	sort(a+1,a+n+n+1);
    	int left = 0,right = n;
    	while(left<right)
    	{
    		int mid = left+((right-left)>>1);
    		bool ok = true;
    		for(int i=mid*2+1; i<=n+n; i++)
    		{
    			if(a[i]+a[n+n+mid+mid+1-i]<m) {ok = false; break;}
    		}
    		if(ok==true) {right = mid;}
    		else {left = mid+1;}
    	}
    	int pos = 2*right;
    	int ans = 0;
    	for(int i=1; i<=pos; i++) ans = max(ans,a[i]+a[pos+1-i]);
    	for(int i=pos+1; i<=n+n; i++) ans = max(ans,(a[i]+a[n+n+pos+1-i])-m);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    第一次结对编程作业
    第7组 团队展示
    第一次个人编程作业
    js学习笔记(1)
    第一次博客作业
    期末总结
    王者光耀团队作业
    第四次c++作业
    c++第三次作业
    第一次编程作业
  • 原文地址:https://www.cnblogs.com/suncongbo/p/11603804.html
Copyright © 2011-2022 走看看