虽然是个签到,但是这个题出的挺好的。
思路:首先可以看到和顺序无关,所以sort。
sort完之后序列如下:
原本分数 a1 a2 a3 a4 a5 a6 a7
增加分数: 7 6 5 4 3 2 1
想要让a1最大,就让a1+7,同时由于序列是单增的,贪心让增加分数递减。如果这时候后面存在总分比他还大的,那么他永远不会是总冠军。
那到了a4呢?我们同样贪心让a4+7,注意是加7.这时候要a4前面的数比a4小,加的分数比a4小,自然不用考虑。要让a4后面的数尽可能小,那么同理让加分多的放a4前,后面剩加分小的,也就是递减放。
如何快速判断后面的序列加上一段固定的值后形成的新值是否大于当前的值+n。
可以st/线段树。但昨天的经验表明:取后缀最大值即可。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=3e5+1000;
typedef long long LL;
LL a[maxn],b[maxn];
LL sum[maxn];
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL n;cin>>n;
sum[n+1]=0;
for(LL i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
for(LL i=1;i<=n;i++){
b[i]=n-i+1;
}
for(LL i=n;i>=1;i--){
sum[i]=max(sum[i+1],b[i]+a[i]);
}
LL ans=1;
for(LL i=1;i<=n-1;i++){
if(a[i]+n>=sum[i+1]){
ans++;
}
}
cout<<ans<<endl;
return 0;
}