C. Array Destruction(思维+树形结构+枚举)

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

思路:首先要满足条件第一个值是最大值,然后顺着题目的思路走,会发现答案形成了一颗树。

除了7之外,14=11+3;11=6+5;6=4+2;4=3+1;而且左儿子都是最大的。因此最大值确定了,左儿子一定是一个次大值,右儿子是父亲和左儿子的差。那么问题来了,还有一个7应该怎么扔呢,如何判定对结果的影响呢。枚举,我们枚举这个7,每次在multiset里去logn的查找和修改,看每次结果是否满足。

(才意识到multiset有找最大值的函数prev)

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5;
typedef long long LL;
typedef pair<LL,LL>P;
multiset<LL>s;
LL a[maxn];
LL temp;
P ans[maxn];
LL n;
bool solve(LL p){
    LL x=p;
    for(LL k=1;k<=n-1;k++){
        LL mavx=*prev(s.end());
        s.erase(s.find(mavx));
        if(s.find(x-mavx)!=s.end()){
            s.erase(s.find(x-mavx));
            ans[++temp]={mavx,x-mavx};
            x=mavx;
        }
        else break;
    }
    if(temp==n) return 1;
    else return 0;
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL t;cin>>t;
  while(t--){
    cin>>n;
    s.clear();
    for(LL i=1;i<=2*n;i++){
        cin>>a[i];
    }
    sort(a+1,a+1+2*n);
    LL res=0;
    ///枚举第一次和最大值搭配的数字
    for(LL i=1;i<=2*n-1;i++){
        s.clear();
        for(LL j=1;j<=n*2;j++){
            s.insert(a[j]);
        }
        s.erase(s.find(a[i]));
        s.erase(s.find(a[n*2]));///最大值
        LL p=a[n*2];
        temp=0;
        ans[++temp]={a[n*2],a[i]};
        if( solve(p)==1){
            break;
        }
    }
    if(temp==n){
        cout<<"YES"<<endl;
        cout<<ans[1].first+ans[1].second<<endl;
        for(LL i=1;i<=temp;i++){
            cout<<ans[i].first<<" "<<ans[i].second<<" "<<endl;
        }
    }
    else cout<<"NO"<<endl;
  }
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/112859623