[ABC416D] Match, Mod, Minimize 2
题面-[ABC416D] Match, Mod, Minimize 2
算法关键词:贪心,思维题
题目大意:给出两个长度为 \(n\) 的数组 \(A\) 和 \(B\) 和一个取模数 \(M\),可以随意重新排列数组 \(A\),计算 \(\sum_{i=1}^{n}((A_i+B_i) \bmod M)\) 的值,问最小的值是多少。
首先注意到和要对 \(M\) 取模,又看到数据范围中有
\(0\le A_i,B_i \le M\)
也就是说两数相加后最多减去一个 \(M\) 。而我们希望结果最小,就要减去尽可能多的 \(M\),很容易想到用贪心的方法解决。
当然首先要给两数组排个序。欸题目中不是说只排序 \(A\) 数组吗?
因为这道题允许我们排序 \(A\) 数组,而且求和和 \(A\),\(B\) 数组内部的位置没关系,只和 \(A_i\),\(B_j\) 的相对位置有关系,所以实际上两个数组都可以更改顺序。
所以直接排序完后从大到小枚举\(x\),匹配最小的满足\(y\ge M-x\) 的 \(y\)(保证取模后的数最小),如果不存在则匹配最小的未匹配的数即可。
代码实现不长 (开心) ,时间复杂度\(O(Tn)\)。
#include <bits/stdc++.h>
using namespace std;
const int N=300010;
int a[N],b[N];
bool cmp(int x,int y){
return x>y;
}
int main (){
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
int ans=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
ans+=a[i];
}
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
ans+=b[i];
}
sort(a+1,a+n+1);
sort(b+1,b+n+1,cmp);
int sum=0,j=1;
for(int i=1;i<=n;i++){
while(j<=m&&b[j]+a[i]>=m) j++;
if(sum!=j-1) sum++;
}
printf("%d\n",ans-sum*m);
}
return 0;
}
浙公网安备 33010602011771号