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 1ai≥1 ) tokens.
The championship consists of n-1n−1 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^41≤t≤104 ) — 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^51≤n≤2⋅105 ) — 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^91≤ai≤109 ) — 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^52⋅105 .
Output:
The first line contains one integer tt ( 1 \le t \le 10^41≤t≤104 ) — 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^51≤n≤2⋅105 ) — 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^91≤ai≤109 ) — 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^52⋅105 .
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 - 1n−1 场比赛。每场比赛随机抽取两个 token 不为 00 的选手,token 大的一方为胜方,(token 相同则胜方随机选一个),胜方会拿走败方的所有 token。最后会产生一位冠军。
很明显,冠军是谁与每场比赛选取的选手有很大关系。升序输出有可能成为冠军的选手的编号。
思路:我们考虑一个选手如何能成为冠军。容易构造出一种方案:
- 首先先跟所有 token 小于等于自己的选手打若干场然后作为胜方拿走他们的 token
- 然后转战 token 大于自己的初始 token 的选手,从小往大打,如果能打得过所有选手他就成冠军
第一步肯定是能够实现的(除非是 token 垫底的那个选手),关键就在于他拿了所有比自己弱的选手的 token 之后能不能打得过那些比自己一开始强的选手。
考虑到这里,我们很自然的会先把所有选手按照 token 从小到大排个序再求一个前缀和。记排序过后的第 i个选手的 token 为 bi,前缀和为 si。不难发现如果 si≥bi+1 的话这个选手就有机会打赢第 i + 1 个选手。然后他现在有的 token 即为 s_{i + 1}si+1。看到这里“第 ii 个选手能不能赢”的问题就已经被转化成了“第 i+1i+1 个选手能不能赢”的问题了,不难归纳出如下结论:
如果第 i 个选手能成为冠军,并且 bi≤si−1,那么第 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; }