“最大的威胁度”算法(请各路英雄好汉检阅!)

//小雪非常关注自行车比赛,尤其是环滨湖自行车赛。一年一度的环滨湖自行车赛,需要选手们连续比赛数日,最终按照累计得分决出冠军。
//今年一共有N位参赛选手。每一天的比赛总会决出当日的排名,第一名的选手会获得N点得分,第二名会获得N-1点得分,第三名会获得N-2点得分,依次类推,最后一名会获得1点得分。保证没有选手会排名相同。
//在之前的数日较量中,N位选手已经分别累计了一些分数。现在即将开始的是最后一天的比赛。小雪希望知道有多少位选手还有可能获得最终的冠军,也就是说还有多少选手有可能通过最后一天的比赛获得累计总分第一名。

//第一行输入一个整数N,表示参赛选手总数,保证3<=N<=300000。
//之后N行,其中第i行输入一个整数B[i]表示第i位选手已经获得的累计分数,满足0<=B[i]<=2000000。
//输出只有一行,只输出一个整数,表示有多少位选手有可能获得最终的冠军。

#include <cstdio>
#include <iostream>
#include <cmath>

using namespace std;

int n , k , kl;
int forn , forBs , forBss , forBss2 , forBssk , maxs , cu , co;
int B[300001] , Bs[2000001] , Bss[2000001] , Bssmin[2000001];

void prep()
{

//在这道题中,我们引入变量Bssmin:“最大的威胁度”。
//我们假设要求的人在最后一场比赛中是冠军,而其他的人则是分数越高、最后一次比赛名次越低。
//那么,每一个总分高于他的人,都会对他的冠军造成“威胁”。
//威胁度=分数+在此分数及之前一共有多少人。
//显然,一旦某个人的威胁度超过了他的分数,他就绝无可能获得冠军了。

scanf("%d",&n);
for (forn=1;forn<=n;forn++)
{
scanf("%d",&B[forn]);
if (maxs < B[forn]) maxs = B[forn];//取最大值
}

for (forn=1;forn<=n;forn++)
if (maxs < B[forn]+n) Bs[B[forn]]++;//通过最大值,初步判断有哪些选手可以超越冠军,并把当前的分数出现次数记录下来

for (forBs=maxs;forBs>=1;forBs--)
if (Bs[forBs] > 0) Bss[++forBssk] = forBs;//然后,将所有出现过的分数记录下来

for (forBss=2;forBss<=forBssk;forBss++)//冠军没有威胁,因此我们从2开始
{
k = k + Bs[Bss[forBss-1]];//统计 在此分数及之前一共有多少人
if (Bss[forBss-1] + k > kl)//在一定的分数之后,同一个分数对所有剩下的选手的威胁都是最大的,因此我们需要找出它
{
kl = Bss[forBss-1] + k;
Bssmin[forBss] = kl;//确定一个分数段收到的最大威胁
}
}
return;
}

void sear()
{
for (forBss=1;forBss<=forBssk;forBss++)
if(Bss[forBss] + n > Bssmin[forBss]) co = co + Bs[Bss[forBss]];

printf("%d",co);
return;
}

int main()
{
prep();
sear();
return 0;
}

//英国

//国际上造成最大威胁的国家是 芬兰。
//他们对我们的威胁是226.1。
//—————————————————————
//你可能并没有被这个国家威胁。
//他们的好战度可以合理化你的侵略行为。(笑)

1 条评论

  • 1

信息

ID
1988
难度
5
分类
(无)
标签
(无)
递交数
518
已通过
175
通过率
34%
被复制
4
上传者