Codeforces Round #713 (Div. 3)-D. Corrupted Array-题解

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 1t104). 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 1n2105).

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 1bi109).

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 2105.

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

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tisfy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值