题解:P14029 【MX-X20-T3】「FAOI-R7」重排序列(update)

· · 题解

我们要求的是

变形一下就是 $\sum a_i \mod m + b_i \mod m - [a_i \mod m + b_i \mod m \ge m] \times m$。 再变形一下就是 $\sum a_i \mod m + \sum b_i \mod m - m \cdot \sum [a_i \mod m + b_i \mod m \ge m]$。 因为 $\sum a_i \mod m$ 和 $\sum b_i \mod m$ 是个定值,所以我们要让答案最大即要让 $\sum [a_i \mod m + b_i \mod m \ge m]$ 最小。 考虑让最小的 $a_i \mod m$ 匹配最大的 $b_i \mod m$。 第一种情况,若此时 $a_i \mod m + b_i \mod m \ge m$ 则无论 $i$ 取何值均无法满足 $a_i \mod m + b_i \mod m < m$。所以对于这种情况我们使用最大的 $a_i \mod m$ 与 最大的 $b_i \mod m$ 匹配一定不劣。 第二种情况,若此时 $a_i \mod m + b_i \mod m < m$ 那么此时直接将最小的 $a_i$ 与最大的 $b_i$ 匹配一定不劣。 匹配后将匹配的元素删去。 最后只需要统计整个序列中匹配时,情况一的数量即可求出答案。 ## **code** ```cpp #include<bits/stdc++.h> using namespace std; #define N 200005 int n, m, as[N]; long long ans; struct node{ int id, w, w2; } a[N], b[N]; inline bool cmp(node x, node y) { return x.w < y.w; }; int main() { ios::sync_with_stdio(false); cin.tie(0); int t; cin >> t; while(t--) { ans = 0; cin >> n >> m; for(int i = 1; i <= n; ++i) { cin >> a[i].w; a[i].w %= m, a[i].id = b[i].id = i, ans += a[i].w; } for(int i = 1; i <= n; ++i) { cin >> b[i].w; b[i].w2 = b[i].w, b[i].w %= m, ans += b[i].w; } sort(a + 1, a + n + 1, cmp), sort(b + 1, b + n + 1, cmp); int mx = n; for(int i = 1, j = n; j; --j) { if(a[i].w + b[j].w >= m) as[a[mx--].id] = b[j].w2, ans -= m; else as[a[i++].id] = b[j].w2; } printf("%lld\n", ans); for(int i = 1; i <= n; ++i) printf("%d ", as[i]); putchar('\n'); } return 0; } ```