Accidental Victory(前缀和、排序)

题目链接

题目描述:

A championship is held in Berland, in which nn players participate. The player with the number ii has a_iai ( a_i \ge 1ai1 ) tokens.

The championship consists of n-1n1 games, which are played according to the following rules:

  • in each game, two random players with non-zero tokens are selected;
  • the player with more tokens is considered the winner of the game (in case of a tie, the winner is chosen randomly);
  • the winning player takes all of the loser's tokens;

The last player with non-zero tokens is the winner of the championship.

All random decisions that are made during the championship are made equally probable and independently.

For example, if n=4n=4 , a = [1, 2, 4, 3]a=[1,2,4,3] , then one of the options for the game (there could be other options) is:

  • during the first game, the first and fourth players were selected. The fourth player has more tokens, so he takes the first player's tokens. Now a = [0, 2, 4, 4]a=[0,2,4,4] ;
  • during the second game, the fourth and third players were selected. They have the same number of tokens, but in a random way, the third player is the winner. Now a = [0, 2, 8, 0]a=[0,2,8,0] ;
  • during the third game, the second and third players were selected. The third player has more tokens, so he takes the second player's tokens. Now a = [0, 0, 10, 0]a=[0,0,10,0] ;
  • the third player is declared the winner of the championship.

Championship winners will receive personalized prizes. Therefore, the judges want to know in advance which players have a chance of winning, i.e have a non-zero probability of winning the championship. You have been asked to find all such players.

Input:

The first line contains one integer tt ( 1 \le t \le 10^41t104 ) — the number of test cases. Then tt test cases follow.

The first line of each test case consists of one positive integer nn ( 1 \le n \le 2 \cdot 10^51n2105 ) — the number of players in the championship.

The second line of each test case contains nn positive integers a_1, a_2, \ldots, a_na1,a2,,an ( 1 \le a_i \le 10^91ai109 ) — the number of tokens the players have.

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

Output:

The first line contains one integer tt ( 1 \le t \le 10^41t104 ) — the number of test cases. Then tt test cases follow.

The first line of each test case consists of one positive integer nn ( 1 \le n \le 2 \cdot 10^51n2105 ) — the number of players in the championship.

The second line of each test case contains nn positive integers a_1, a_2, \ldots, a_na1,a2,,an ( 1 \le a_i \le 10^91ai109 ) — the number of tokens the players have.

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

 

Example:

input:

2
4
1 2 4 3
5
1 1 1 1 1

output:

3
2 3 4
5
1 2 3 4 5

题意:一场锦标赛中有 nn 个选手,第 ii 个选手一开始有 a_iai 个 token。进行 n - 1n1 场比赛。每场比赛随机抽取两个 token 不为 00 的选手,token 大的一方为胜方,(token 相同则胜方随机选一个),胜方会拿走败方的所有 token。最后会产生一位冠军。

很明显,冠军是谁与每场比赛选取的选手有很大关系。升序输出有可能成为冠军的选手的编号。

思路:我们考虑一个选手如何能成为冠军。容易构造出一种方案:

  • 首先先跟所有 token 小于等于自己的选手打若干场然后作为胜方拿走他们的 token
  • 然后转战 token 大于自己的初始 token 的选手,从小往大打,如果能打得过所有选手他就成冠军

第一步肯定是能够实现的(除非是 token 垫底的那个选手),关键就在于他拿了所有比自己弱的选手的 token 之后能不能打得过那些比自己一开始强的选手。

考虑到这里,我们很自然的会先把所有选手按照 token 从小到大排个序再求一个前缀和。记排序过后的第 i个选手的 token 为 bi,前缀和为 si。不难发现如果 sibi+1 的话这个选手就有机会打赢第 i + 1 个选手。然后他现在有的 token 即为 s_{i + 1}si+1。看到这里“第 ii 个选手能不能赢”的问题就已经被转化成了“第 i+1i+1 个选手能不能赢”的问题了,不难归纳出如下结论:

如果第 i 个选手能成为冠军,并且 bisi1,那么第 i -1 个选手也能成为冠军。说明如果第 i 个选手没机会成为冠军,那么初始 token 比他低的也都没有机会了。

所以直接建结构体排序就可以了。

#include<bits/stdc++.h>
#include<iostream>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
using namespace std;
typedef unsigned long long ull;
typedef  long long ll;
typedef pair<ll,ll> pi;
#define IOS std::ios::sync_with_stdio(false)
#define ls p<<1
#define rs p<<1|1
#define mod 1000000000 + 7
#define PI acos(-1.0)
#define INF   1e9
#define N 2000000 + 5
/*********************Code*********************/
ll t,n,sum[N];
struct node{
    ll val,id;
}e[N];
bool cmp1(node a,node b){
    return a.val < b.val;
}
bool cmp2(node a,node b){
    return a.id < b.id;
}
int main(void){
    IOS;
    cin>>t;
    while(t--){
        cin>>n;
        for(ll i = 1;i <=n;i++){
            cin>>e[i].val;
            e[i].id = i;
        }
        sort(e+1,e+n+1,cmp1);
        for(ll i = 1;i <=n;i++){
            sum[i] = sum[i-1] + e[i].val;
        }
        ll ans = 0,cnt = 0;
        for(ll i = n;i >=1;i--){
            cnt++;
            if(e[i].val>sum[i-1]){
                ans =e[i].val;
                break;
            }
        }
        sort(e+1,e+n+1,cmp2);
        cout<<cnt<<endl;
        for(ll i = 1;i <=n;i++){
            if(e[i].val>=ans)
                cout<<i<<" ";
        }
        cout<<endl;
    }
    return 0;
}

 

posted @ 2021-02-20 09:26  阿涅—Rachel  阅读(119)  评论(0)    收藏  举报