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;
}