CF1474C Array Destruction 題解 貪心

題目鏈接:http://codeforces.com/contest/1474/problem/C

解題思路:貪心。和 \(x\) 必定是單調遞減的(因爲所有 \(a_i\) 都大於 \(0\))。所以一開始的 \(x\) 必定是最大的那個數加上另一個數,最大的那個數是可以確定的, 另一個數 不能確定,所以需要枚舉。

所有一開始需要枚舉 \(2n-1\)另一個數 ,和最大的那個數一起確定初始的 \(x\),然後我們接下來每一步都知道當前的 \(x\),並且組成 \(x\) 的兩個數中有一個是當前沒有使用過的最大值,另一個數(\(x -\) 最大數)可以二分得到,總的時間複雜度爲 \(O((2n-1) \times n \log n) = O(n^2 \log n)\)

示例代碼:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2020;
int T, n, a[maxn], ans;
multiset<int> st;
vector<pair<int, int> > vec;

bool _check(int ii) {
    st.clear();
    for (int i = 0; i < 2*n-1; i ++) {
        if (i == ii) continue;
        st.insert(a[i]);
    }
    vec.clear();
    vec.push_back({a[2*n-1], a[ii]});
    ans = a[2*n-1] + a[ii];
    int tmp = a[2*n-1];
    for (int i = 1; i < n; i ++) {
        multiset<int>::iterator it = st.end(), it2;
        it --;
        int x = *it;
        st.erase(it);
        it2 = st.lower_bound(tmp - x);
        if (it2 == st.end()) return false;
        int y = *it2;
        if (x + y != tmp) return false;
        vec.push_back({x, y});
        tmp = max(x, y);
        st.erase(it2);
    }
    return true;
}

bool check() {
    for (int i = 0; i < 2*n-1; i ++) if (_check(i)) return true;
    return false;
}

int main() {
    scanf("%d", &T);
    while (T --) {
        scanf("%d", &n);
        for (int i = 0; i < 2*n; i ++) scanf("%d", a+i);
        sort(a, a+2*n);
        if (check()) {
            puts("YES");
            printf("%d\n", ans);
            for (auto x : vec) printf("%d %d\n", x.first, x.second);
        }
        else puts("NO");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章