洛谷 P7542 MALI 题解
又双叒叕水了一篇题解...
题目简述
对于两个序列 A,序列 B,长度一致;
共 \(n\) 次操作,
每次操作都会向这两个序列增加数字。
在每次操作后,要求对每个序列中的每个数字配对,要让配对数之和的最大值最小。
Solution
贪心。
对每时每刻的序列排序,\(a\) 中从小到大与 \(b\) 中从大到小配对。
证明:
对于序列中最小的 \(a_i\),序列最大的\(b_j\),
若将 \(a_i\) 替换成 \(a_k\) 且 \(a_k>a_i\) ,此时必有 \(a_k+b_j>a_i+b_j\),不必原计划更优;
若将 \(b_j\) 替换成 \(b_k\),且 \(b_j<b_k\),则必有 \(a_z>a_i\) 需要与 \(b_j\) 配对。所以必有更大值 \(a_z+b_j>a_i+b_j\),也不必原计划更优。
所以,每次选择最小和最大的配对可以得到最优解。
可惜直接排序时间复杂度不够。
时间复杂度为 \(O(n^2\log n)\),\(n\leq 10^5\),超时。
优化。
1、桶优化
发现 \(1\leq a_i,b_j\leq 100\),所以考虑直接桶排。
时间复杂度降为 \(O(n^2)\)。
2、连续配对优化
发现当 \(a_i,b_j\) 出现多次时,会直接配出 \(\min(a_i,b_j)\) 组一样的配对。
所以对于桶中 \(a_i,b_j\) ,每次配对时,对应减少 \(\min(a_i,b_j)\) 即可。
最坏时间复杂度为 \(O(100n)\) ,不会超时。
AC Code
#include<bits/stdc++.h>
using namespace std;
int a[101],b[101];
int am[101],bm[101];
int main()
{
int n,k,maxn=-414231;
cin>>n;
for(int i=1;i<=n;i++)
{
maxn=-414231;
cin>>k,am[k]++;
cin>>k,bm[k]++; //优化1
memcpy(a,am,sizeof(am));
memcpy(b,bm,sizeof(bm)); //复制桶
int l=1,r=100;
while(r>=1&&l<=100)
{
while(!a[l]) l++;
while(!b[r]) r--;
if(r<1||l>100) break;
maxn=max(maxn,l+r);
minx=min(a[l],b[r]);
a[l]-=minx;b[r]-=minx; //优化2
}
cout<<maxn<<endl;
}
return 0;
}
qwq

浙公网安备 33010602011771号