天天看點

2021牛客多校1

寫在前面:本蒟蒻不會Markdown或者LaTeX的文法,是以想用數學公式都是去Wps裡寫的公式然後截屏的。還挺好用的

然後我認為難度比較大的題目就暫時不補了

G:Game of Swapping Numbers

題目連結

題目大意: 給兩個整數 N, K, 和兩個數組,

求剛好 K 此操作後的

2021牛客多校1

題目思路: 兩個序列一共有 2 * n 個數。如果可以從中任意兩兩配對的話,得到的最大的內插補點和是較大的 n 個數減去較小的 n 個數。可以看作把較大的 n 個數配置設定 + 号,給較小的 n 個數 配置設定 - 号。

如果 Ai 和 Bi 是異号,則不需要與其他位置的數交換;

如果 Ai 和 Bi 是同号,都為 + 的時候需要找到一對 Aj 和 Bj 都是 - 的交換 Ai和 Aj,都為 - 的時候需要找到一對 Aj 和 Bj 都是 + 的交換 Ai和 Aj。

下面給出如何計算交換後答案變優的值

2021牛客多校1

其實也可以分析出 4 個數中最大值在兩次計算中都是 + 号, 最小值在兩次計算中都是 - 号,兩次計算的內插補點會将其抵消,剩餘兩數在兩次計算中就是

d - a 和 a - d,變優的值就是 2 * d - 2 * a 了。

如果不分别考慮 a 和 c,b 和 d 之間的大小關系,那麼得到的通式就是

2 * min(b, d) - 2 * max(a, c)。

當 n > 2 的時候恰好交換 k 次 等同與至多交換 k 次,因為可以将已滿足 Ai 和 Bi 異号,Aj 和 Bj 異号,交換 Ai 和 Bj,并不會使答案變劣;

當 n = 2 的時候特判。

解題: 我們希望每次交換都讓結果變優得盡可能多,是以将 A 數組取 Ai和 Bi 的較小值,是以将 B 數組取 Ai和 Bi 的較大值,再對兩數組分别排序。

對于 A[i] 中每個元素,如果他是 + 号,那麼因為他之前對應的另一個元素 B[j] 比他大是以該元素也是 + 号;

對于 B[p] 中每個元素,如果他是 - 号,那麼因為他之前對應的另一個元素 A[q]比他小是以該元素也是 -号;

此時,交換兩個位置的 A[i] 和 A[q] 可以使答案變優 2 * A[i] - 2 * B[p]。

詳細操作請看代碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<double, double> P;
const int INF = 0x3f3f3f3f;
const int MAX_N = 5e5 + 10;
const int MOD = 1e9 + 7;
const double esp = 1e-9;
int n, k;
int a[MAX_N], b[MAX_N];
void solve(){
    ll res = 0;
    scanf("%d%d", &n, &k); 
    for(int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    for(int i = 0; i < n; i++){
        scanf("%d", &b[i]);
        if(a[i] > b[i]) swap(a[i], b[i]); //a[i] 取較小值,b[i]取較大值
        res += b[i] - a[i]; //計算初始答案
    }
    if(n == 2){ //特判
        int res1 = abs(a[0] - b[0]) + abs(a[1] - b[1]);
        int res2 = abs(a[1] - b[0]) + abs(a[0] - b[1]);
        if((k & 1) != 1) printf("%d\n", res1);
        else printf("%d\n", res2);
        return;
    }
    k = min(n, k); // k 可能大于 n, 不縮小會使後面數組越界;
    //排序
    sort(a, a + n);
    sort(b, b + n);
    for(int i = 0; i < k; i++){
        int t = a[n - 1 - i] - b[i]; //變優的值
        if(t > 0) res += t * 2;
    }
    printf("%lld\n", res);
}
int main(){
    int TCASE = 1;
//    scanf("%d", &TCASE);
    while(TCASE--) solve();
    return 0;
}