Educational Codeforces Round 141:C. Yet Another Tournament

一、来源:Problem - C - Codeforces

二、题面

image-20230205154012349

三、思路

  1. 读题:

    • 其他人的胜场由位次决定,对于第i位,其胜场为i-1
    • 人数为\(5·10^5\),不是5(看错了)
    • 每个人和自己比较时,可能输可能赢,故其他人最终的胜场是i或i+1
  2. 迭代的思想:(二维不相关)本人最一开始的思路是自下而上遍历先决定胜场,再直接决定名次;(二维相关)事实上胜场与名次两者是无法割裂的,故我们每次和一个人比较,看看能不能打赢他,进而决定能不能到相同的名次n-i+1

  3. 集合的划分:(需要看到的是能否打赢第i位和到n-i+1位次需要的胜场是两个维度的划分)

    • 初次划分

      image-20230205160143424

    • 优化

      image-20230205161107196

四、代码

#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;
}
posted @ 2023-02-05 16:14  Arno_vc  阅读(22)  评论(0编辑  收藏  举报