目录
Codeforces Round #713 (Div. 3)-D. Corrupted Array
传送门
Time Limit: 2 seconds
Memory Limit: 256 megabytes
Problem Description
You are given a number n n n and an array b 1 , b 2 , … , b n + 2 b_1, b_2, \ldots, b_{n+2} b1,b2,…,bn+2, obtained according to the following algorithm:
For example, the array b = [ 2 , 3 , 7 , 12 , 2 ] b=[2, 3, 7, 12 ,2] b=[2,3,7,12,2] it could be obtained in the following ways:
For the given array b b b, find any array a a a that could have been guessed initially.
Input
The first line contains a single integer t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1≤t≤104). Then t t t test cases follow.
The first line of each test case contains a single integer n n n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2 \cdot 10^5 1≤n≤2⋅105).
The second row of each test case contains n + 2 n+2 n+2 integers b 1 , b 2 , … , b n + 2 b_1, b_2, \ldots, b_{n+2} b1,b2,…,bn+2 ( 1 ≤ b i ≤ 1 0 9 1 \le b_i \le 10^9 1≤bi≤109).
It is guaranteed that the sum of n n n over all test cases does not exceed 2 ⋅ 1 0 5 2 \cdot 10^5 2⋅105.
Output
For each test case, output:
If there are several arrays of a a a, you can output any.
Sample Input
4
3
2 3 7 12 2
4
9 1 7 1 6 5
5
18 2 2 3 2 9 2
3
2 6 9 2 1
Sample Onput
2 3 7
-1
2 2 2 3 9
1 2 6
题目大意
给你一个数 n n n并且给你 n + 2 n+2 n+2个数,问你能不能从这 n + 2 n+2 n+2个数里挑出 n n n个数,使得这 n n n个数的和是剩下两个数中的其中一个。
解题思路
从这 n + 2 n+2 n+2个数里挑出 n n n个数,使得这 n n n个数的和是剩下两个数中的其中一个,也就是说,可以有一个数不要。也就是扔掉一个数,剩下 n + 1 n+1 n+1个数中,选出 n n n个,他们的和等于另一个数(记为 t t t)。
那么有这 n + 1 n+1 n+1个数的和等于 2 t 2t 2t。
因此,我们只需要一个一个地尝试仍掉其中一个数,看剩下的数的和是否等于剩下数中某个数的 2 2 2倍。
例如
2 3 7 12 2
当我们尝试将2扔掉时,剩下的数是
3 7 12 2
,他们的和是24
,等于2*12
,因此我们就扔掉了2
并且找到了 3 3 3个数3 7 2
,他们的和是12
。
AC代码
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
ll a[200010];
int main()
{
int N;
cin>>N;//N组测试样例
while(N--)
{
int n;
cd(n);//scanf("%d", &n)
n+=2;//给你n+2个数
ll sum=0;//和初始值为0
map<ll,int>ma;//记录一个数出现过几次
fi(i,0,n)//for(int i=0;i<n;i++)
{
scanf("%lld",&a[i]);//输入a[i]
sum+=a[i];//和+=a[i]
ma[a[i]]++;//a[i]出现的次数++
}
fi(i,0,n)//for(int i=0;i<n;i++)
{
sum-=a[i];//先尝试扔掉这个数
ma[a[i]]--;//出现的次数--
if(sum%2==0&&ma[sum/2])//剩下的数的和是偶数且等于一个数的两倍
{
bool donnot=0;//还没找到这个数
fi(j,0,n)//开始遍历
{
if(j==i);//下标是扔掉这个数,不输出,什么都不干
else if(donnot==0&&a[j]==sum/2)//还没找到 并且 这个数等于和的一半
{
donnot=1;//找到了
}
else//否则输出
{
printf("%lld ",a[j]);
}
}
puts("");//换行
goto loop;//结束这组样例
}
sum+=a[i];//不能扔掉这个数,和加上
ma[a[i]]++;//出现次数加上
}
puts("-1");//没跳到下面一行。说明找不到,就输出-1
loop:;//跳到这里
}
return 0;
}
原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/115599125