【Codeforces Round #695 (Div. 2) C】Codeforces Round #695 (Div. 2)
阿新 • • 發佈:2021-01-11
題目連結
翻譯
給你 \(3\) 個多重集,第 \(i\) 個集合有 \(n[i]\) 個數字。
從兩個不同集合中分別取出數字 \(x\) 和 \(y\),則從兩個集合中分別刪去 \(x\) 和 \(y\), 然後在第 \(1\) 個集合中(取出 \(x\)
的那個集合) 加入元素 \(x-y\)。
要求最後只有一個集合中剩下一個數字,問你這個數字最大可以是多少。
題解
思維
把操作 \((x,y)\) 看做是有向樹的一條邊,邊由兒子節點指向父節點,其中兒子節點表示 \(y\),父節點表示 \(x\)。
即操作過後, 兒子節點沒了,父節點變成 \(x-y\)
那麼,形成的這棵樹有 \(n_1+n_2+n_3\) 個節點。
模擬一下會發現,最後剩下的一個數字就為樹中偶數層的節點之和減去奇數層的節點之和(根視為第 \(0\) 層)。
問題就轉化成讓奇數層上數字之和最小。
但是奇數層上的數字是有限制的,會發現奇數層上的節點要滿足以下兩個條件之一:
- 1.奇數層上的節點全都來自同一個集合 \(X\) 中,且這個集合 \(X\) 中的全部元素都在奇數層上。
- 2.奇數層上的節點來自至少兩個集合中的數字。
證明如下: 如果奇數層上的節點全都來自同一個集合 \(X\) ,但是沒有包括 \(X\) 中的全部元素的話,那麼 \(X\)
中剩下的元素怎麼辦?只能放在偶數層了,但是這就和題目中的操作衝突了,因為這個偶數層的節點會和奇數層
的來自同一集合中的元素進行合併操作了,非法。所以只能全都在同一層。
而如果奇數層上的節點至少來自兩個集合則沒有這個煩惱了,父節點是相同集合的元素的話,就全都扔在另外一個
集合的節點下面就好了。
這樣的話,我們就最多用一個 \(3\) 層的如上所述的樹就能完成構造了,奇數層就是第 \(1\) 層,可以是兩個集合中各自
最小的元素的加和,或者全都來自同一個集合中的數字的加和。排個序,考慮一下這幾種情況就好。
程式碼
#include <bits/stdc++.h> #define LL long long using namespace std; const int N = 3e5; int n[4]; int a[4][N + 10]; int main() { #ifdef LOCAL_DEFINE freopen("in.txt", "r", stdin); #endif ios::sync_with_stdio(0), cin.tie(0); for (int i = 1; i <= 3; i++) { cin >> n[i]; } for (int i = 1; i <= 3; i++) { for (int j = 1; j <= n[i]; j++) { cin >> a[i][j]; } sort(a[i] + 1, a[i] + 1 + n[i]); } LL ans = 0; LL temp1 = 0; for (int i = 1; i <= 3; i++) { for (int j = 1; j <= n[i]; j++) { temp1 += a[i][j]; } } //1.奇數層全都來自同一個bag for (int i = 1; i <= 3; i++) { LL temp2 = 0; for (int j = 1;j <= n[i];j++){ temp2 += a[i][j]; } ans = max(ans, temp1 - 2 * temp2); } //1.奇數層來自兩個不同的bag for (int i = 1; i <= 3; i++) { LL temp2 = 0; //1,2 temp2 = a[1][1] + a[2][1]; ans = max(ans, temp1 - 2 * temp2); //1,3 temp2 = a[1][1] + a[3][1]; ans = max(ans, temp1 - 2 * temp2); //2,3 temp2 = a[2][1] + a[3][1]; ans = max(ans, temp1 - 2 * temp2); } cout << ans << endl; return 0; }