Codeforces Round #713(Div. 3)
D.Corrupted Array
题意:给你一个n+2长度的数组b,根据特定算法还原数组a,该算法要求:
No1.b可以洗牌(顺序不影响结果)
No2.
b
i
=
a
i
(
1
<
=
i
<
=
n
)
b_i=a_i(1<=i<=n)
bi=ai(1<=i<=n)
No3.
b
i
+
1
=
a
1
+
a
2
+
.
.
.
+
a
n
b_{i+1}=a_1+a_2+...+a_n
bi+1=a1+a2+...+an
No4.
b
2
=
x
(
1
<
=
x
<
=
1
0
9
)
b_2=x(1<=x<=10^9)
b2=x(1<=x<=109)
No5. a数组是推定的
有解输出序列a,无解输出-1
思路:因为有个数是其他数的前缀和,所以这个数肯定很大,考虑到 b i < = 1 0 9 b_i<=10^9 bi<=109 , 所以 a i < = 1 0 9 a_i<=10^9 ai<=109 , 然后可以大胆构造了
取b中最大值先作前缀和试试,接下来要在其余n+1个数找n个数使得它们的和等于这个前缀和,舍弃的那个数作x即可
若此时无解则继续尝试b的次大值作前缀和,b的最大值舍去(不舍去的话作为成员加入前缀和肯定比次大值大,相互矛盾,所以只能舍去), 在n+1中数中找n个数使其和等于次大值,所以次大值的2倍等于前n+1小的数的和,若不满足则无解
对于要是以b中第3大值(或者是第n大值, n > = 3 n>=3 n>=3)作为前缀和,那么次大值和最大值中只有一个作随机数,另一个必然加入前缀和的成员,又相互矛盾,所以不必继续讨论
Code:
#include<bits/stdc++.h>
#define int long long
#define rep(i,a,n) for(int i = a; i<=n; i++)
#define pb push_back
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int mxn=2e5+10;
int b[mxn], a[mxn];
auto solve()->void{
int n;
cin>>n;
rep(i,1,n+2) cin>>b[i];
vector<int> v;
sort(b+1,b+n+3);
int sum=0, lst=b[n+2];
rep(i,1,n+1) sum+=b[i];
int ansi=-1;
rep(i,1,n+1){
if(sum-b[i]==lst) {ansi=i;break;}
}
if(ansi!=-1){
rep(i,1,n+1){
if(i==ansi) continue;
v.pb(b[i]);
}
for(int i=0; i<v.size(); i++) cout<<v[i]<<" \n"[i==v.size()-1];
return;
}
if(b[n+1]==sum-b[n+1]){
rep(i,1,n) cout<<b[i]<<" \n"[i==n];
return;
}
cout<<-1<<'\n';
}
signed main(){
ios;
int t=1;
cin>>t;
while(t--){
solve();
}
return 0;
}