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

153 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

@TOC

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

传送门 Time Limit: 2 seconds Memory Limit: 256 megabytes

Problem Description

You are given a number nn and an array b1,b2,,bn+2b_1, b_2, \ldots, b_{n+2}, obtained according to the following algorithm:

For example, the array b=[2,3,7,12,2]b=[2, 3, 7, 12 ,2] it could be obtained in the following ways:

For the given array bb, find any array aa that could have been guessed initially.

Input

The first line contains a single integer tt (1t1041 \le t \le 10^4). Then tt test cases follow.

The first line of each test case contains a single integer nn (1n21051 \le n \le 2 \cdot 10^5).

The second row of each test case contains n+2n+2 integers b1,b2,,bn+2b_1, b_2, \ldots, b_{n+2} (1bi1091 \le b_i \le 10^9).

It is guaranteed that the sum of nn over all test cases does not exceed 21052 \cdot 10^5.

Output

For each test case, output:

If there are several arrays of aa, 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 

题目大意

给你一个数nn并且给你n+2n+2个数,问你能不能从这n+2n+2个数里挑出nn个数,使得这nn个数的和是剩下两个数中的其中一个。


解题思路

从这n+2n+2个数里挑出nn个数,使得这nn个数的和是剩下两个数中的其中一个,也就是说,可以有一个数不要。也就是扔掉一个数,剩下n+1n+1个数中,选出nn个,他们的和等于另一个数(记为tt)。 那么有这n+1n+1个数的和等于2t2t。 因此,我们只需要一个一个地尝试仍掉其中一个数,看剩下的数的和是否等于剩下数中某个数的22倍。

例如

2 3 7 12 2

当我们尝试将2扔掉时,剩下的数是3 7 12 2,他们的和是24,等于2*12,因此我们就扔掉了2并且找到了33个数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;
}

同步发文于我的CSDN,原创不易,转载请附上原文链接哦~
Tisfy:letmefly.blog.csdn.net/article/det…