CF1474C Array Destruction 題解 貪心
阿新 • • 發佈:2021-01-20
題目連結: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; }