codeforces1474C

https://codeforces.com/problemset/problem/1474/C

题意:

有一个数字x和一个长度为2*n的数组,每次找到两个数字a,b,使得x=a+b,并且删除掉a和b,同时x更新为max(a,b),试问能不能把这个数组全部清除,

思路:

首先排序,每次删除的肯定是这些数中最大的一个a,和x-a,假如删除了较小的a,那么比a大的数字将永远不会被删除,第一次删除的肯定是a[n]和任意一个数(不一定是第一个数字),然后模拟这个过程,每次选择最大的数字,然后删除集合中的指定数字,可以使用set完成,由于有重复,可以使用multiset配合二分函数实现

题解:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
#include <vector>
#define eb emplace_back
#define divUp(a,b) (a+b-1)/b
#define mkp(x,y) make_pair(x,y)
#define all(v) begin(v),end(v)
#define int long long
using namespace std;
typedef unsigned long long ull;
typedef pair<int, int> pii;
bool checkP2(int n) { return n > 0 and (n & (n - 1)) == 0;};
const int N = 2010;
int a[N];
void solve() {
    int n;
    cin >> n;
    n *= 2;
    for (int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + 1 + n);
    multiset<int, greater<int>>s;
    vector<pii> v;
    bool ok = true;
    for (int i = 1; i <= n - 1; i++) {
        s.clear();
        v.clear();
        ok = true;
        int x = a[n];
        for (int j = 1; j <= n - 1; j++) {
            if (j == i) continue;
            else s.insert(a[j]);
        }
        while (s.size()) {
            auto cur = s.begin();
            int cur_v = *cur;
            s.erase(cur);
            auto it = s.find(x - cur_v);
            if (it == s.end()) {
                ok = false;
            }
            if (!ok) break;
            x = max(*it, cur_v);
            v.eb(mkp(*it, cur_v));
            s.erase(it);
        }
        if (ok) {
            cout << "Yes" << endl;
            cout << a[n] + a[i] << endl;
            cout << a[n] << ' ' << a[i] << endl;
            for (auto [x, y] : v) {
                cout << x << ' ' << y << endl;
            }
            return ;
        }
    }
    cout << "No" << endl;
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int _; cin >> _; while (_--)
        solve();
    return 0;
}

posted @ 2021-10-12 22:28  指引盗寇入太行  阅读(51)  评论(0)    收藏  举报