Educational Codeforces Round 141:C. Yet Another Tournament
一、来源:Problem - C - Codeforces
二、题面
三、思路
-
读题:
- 其他人的胜场由位次决定,对于第i位,其胜场为i-1
- 人数为\(5·10^5\),不是5(看错了)
- 每个人和自己比较时,可能输可能赢,故其他人最终的胜场是i或i+1
-
迭代的思想:(二维不相关)本人最一开始的思路是自下而上遍历先决定胜场,再直接决定名次;(二维相关)事实上胜场与名次两者是无法割裂的,故我们每次和一个人比较,看看能不能打赢他,进而决定能不能到相同的名次
n-i+1
-
集合的划分:(需要看到的是能否打赢第i位和到
n-i+1
位次需要的胜场是两个维度的划分)-
初次划分
-
优化
-
四、代码
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=5e5+10; //经典错误,只看到5,没看到5*10^5
//考虑胜场与赢谁的关系:若两者之间没有关系,可以先后求;若两者直接有关系需要考虑变换进而一起求(两个思维的区别很重要)
int arr[N],b[N],pre[N];
int main(){
int t;
cin >> t;
while(t--){
int n,m;
cin >> n >> m;
for(int i=1;i<=n;i++){
cin >> arr[i];
b[i]=arr[i]; //用于之后排序
}
sort(b+1,b+1+n);
pre[0]=0;
for(int i=1;i<=n;i++){
pre[i]=b[i]+pre[i-1];
//cout << "pre[" << i << "]=" << pre[i] << endl;
}
int ans=m>=b[1]?n:n+1; //这里不是m>=arr[1],因为第一个人只赢了0场
//以i=1为下标,若赢当前位,共胜i-1场可以到达同位置;若不赢当前位,胜i场可以到达同位置
for(int i=2;i<=n;i++){
//cout << "i:" << i << " arr[i]+pre[i-1]:" << arr[i]+pre[i-1] << " pre[i]" << pre[i] << endl;
if(m>=arr[i]){ //能赢当前位
else if(arr[i]<=b[i-1]){ //pre[i-1]中已经包含arr[i]
if(m>=pre[i-1]){
ans=n+1-i;
}
}else{
if(m>=arr[i]+pre[i-2]){
ans=n+1-i;
}
}
}
}
cout << ans << endl;
}
return 0;
}