欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

cf 1474 C. Array Destruction(暴力,数据结构)

程序员文章站 2022-06-01 21:33:28
...

题目链接:https://codeforces.ml/contest/1474/problem/C

题意:T组样例(T<=1000),每一组样例输入n(1<=n<=1000),然后输入一个长度为2*n的数组a,(1<=ai<=1e6)。

然后问是否满足条件,如果满足先打印"YES",然后输入最先取出的两个数的和,再每一次取出两个数,满足和与上一次取出的两个数中的最大值相等,如果能一直取到一个数都不剩,则满足条件,否则打印"NO"。

示例:

input:::
4
2
3 5 1 2
3
1 1 8 8 64 64
2
1 1 2 4
5
1 2 3 4 5 6 7 14 3 11
output:::
YES
6
1 5
2 3
NO
NO
YES
21
14 7
3 11
5 6
2 4
3 1

 

题解/总结:

1.set<ll,greater<ll> > st;表示大优先集合;st.begin()只是迭代器;st配合数组或者mp是可以模拟multiset的。最次取最大值可以*st.begin(),(如果边取边删的话)不要for(auto i:st)。

2.哎,竟然没注意到所有N的和不大于1000,所以没敢暴力。许久没打cf了,还是因为在家里不习惯??总犯一些很傻的错误。

3.多写函数,方便直接调用!!!!!!!!!!!

4.最大值一定能作为mx,每次只能从剩下的最大值作为mx开始,所以如果开始确定了选的另一个数,那么删除方法就是固定的了,只需要再判断是否能按照这个删除方法删除。

5.直接暴力,时间复杂度大概O(nlogn*nlogn)

代码:

#include <bits/stdc++.h>

#define ll int
#define pi acos(-1)
#define pb push_back
#define mst(a, i) memset(a, i, sizeof(a))
#define pll pair<ll, ll>
#define fi first
#define se second
#define mp(x,y) make_pair(x,y)
#define rep(i,a,n)  for(ll i=a;i<=n;i++)
#define per(i,n,a)  for(ll i=n;i>=a;i--)
#define dbg(x) cout << #x << "===" << x << endl
#define dbgg(l,r,x) for(ll i=l;i<=r;i++) cout<<x[i]<<" ";cout<<"<<<"<<#x;cout<<endl

using namespace std;

template<class T>void read(T &x){T res=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){res=(res<<3)+(res<<1)+c-'0';c=getchar();}x=res*f;}
void print(ll x){if(x<0){putchar('-');x=-x;}if(x>9)print(x/10);putchar(x%10+'0');}
const ll maxn = 1e6 + 10;
const ll mod = 1e9+7;

ll n,a[maxn];
set<ll,greater<ll> > st;
unordered_map<ll,ll> val;
bool cmp(ll a,ll b){
    return a>b;
}
bool ok(ll id){//判断最开始取a[1]和a[id]的时候是否能取完 
    ll mx=a[1];//上一次取的两个数中的最大值 
    val[a[1]]--;if(val[a[1]]==0) st.erase(a[1]);
    val[a[id]]--;if(val[a[id]]==0) st.erase(a[id]);
    while(st.size()){
    	ll i=*st.begin();//每次取st中最大值 
        if(val[mx-i]==0||(2*i==mx&&val[i]<2)) break;//取不到直接false 
        else{
        	//取i,mx-i 
            val[mx-i]--;if(val[mx-i]==0) st.erase(mx-i);
            val[i]--;if(val[i]==0) st.erase(i);
            mx=max(i,mx-i);
        }
    }
    if(st.size()==0) return true;
    return false;
}
void add(){
    val.clear();
    st.clear();
    rep(i,1,2*n){
        val[a[i]]++;
        if(a[i]!=a[i-1]) st.insert(a[i]);//防止重复 
    }
}
void Print(ll a,ll b){//打印两个数 
    print(a),putchar(' '),print(b),puts(""); 
}
void solve(ll id){//"YES"时输出答案 ,与判断步骤一致 
    ll mx=a[1];
    val[a[1]]--;if(val[a[1]]==0) st.erase(a[1]);
    val[a[id]]--;if(val[a[id]]==0) st.erase(a[id]);
    Print(a[1],a[id]); 
    while(st.size()){
    	ll i=*st.begin();
        if(val[mx-i]==0||(2*i==mx&&val[i]<2)) break;
        else{
            val[mx-i]--;if(val[mx-i]==0) st.erase(mx-i);
            val[i]--;if(val[i]==0) st.erase(i);
            Print(i,mx-i);mx=max(i,mx-i);
        }
    }
}
int main() {
    ll _s = 1;
    read(_s);
    //freopen("testdata.in","r",stdin);
	//freopen("testout.out","w",stdout);
    for (ll _=1;_<=_s;_++) {
        read(n);
        rep(i,1,2*n) read(a[i]);
        sort(a+1,a+1+2*n,cmp);
        ll p=0;//删除id的时候满足条件 
        a[0]=-1;//防止重复 
        rep(i,2,2*n){
             if(a[i]==a[i-1]&&i!=2) continue;
            add();
            if(ok(i)){
                p=i;break;//找到就跳出 
            }
        }
        if(p==0) puts("NO");
        else{
            puts("YES");
            cout<<a[1]+a[p]<<endl;
            add();
            solve(p);
        }  
    }
    return 0;
}

 

相关标签: 暴力 数据结构