这题好难啊~~~~攀攀好厉害啊~~~~~经过我们两天的交流终于弄明白了啊~~~~~~求赞求赞啊啊~~~~~~~~
目前好像只有这一篇解题报告,大体上写的很详细:点击打开链接
这题主要方法就是分向前和向后统计最大挑战次数,与自身挑战成功的值比较
为什么要分向前和向后来统计呢?这个小攀攀跟我解释了半天我也只是一知半解。。有问题请找小攀攀
我就解释下里面提到的,与前面和与后面相互超越 的最大次数
这个最大次数,指的是,超过前面所有人,到第一个,最多需要多少次挑战,这里先不管自身到底能挑战成功多少次
向后也一样,指最多被挑战多少次到最后
那么这个最多挑战次数怎么算呢?
举个例子,例如:编号为1,2,3,4,的4个人挑战成功的次数分别为,1,2,1,2(v[i])
取第三个人为例,
3要到2前面,最坏情况是,2的每一次挑战成功都是对3成功的,这样的话,3到2前面就要2的成功次数+1,即2+1
然后3要到1前面也一样,最多要1的成功次数加1次
然后第i位向前的总次数l[i],就是超过前面每一位需要次数的和,可以用递归来算,l[i]=l[i-1]+v[i]+1
再算向后最多次数
3要到最后,最多就是后面每一位的挑战次数都给3,累加即可,但是。。
向后会遇到一个问题,取第i个为例
如果后面有0的话,0是不可能超过前面任何一个的,0后面的非零值可以挑战到0的前面,再跟i挑战,那么i向后至多只能到所有0的前面
//所以0后面的非零值需要-1,再累加,但是。。这是针对一个0后面的,第二个、第三个0后面,就需要-2、-3。。。以此类推,所以要统计0的个数b
以上的0指的是相对b是0。。就是说 比如已经出现了2个0 后面又出现一个1 这个1不可能超越这两个0 只能超过1个0 这样的话 这个1也就等效是0了
具体的看代码。。。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
__int64 l[1000005],v[1000005],r;
int main()
{
__int64 n,i,j,k,b;
int t=0;
while(~scanf("%I64d",&n))
{
t++;
if(t>=40) continue;//题目测试数据的bug 看discuss就知道了
memset(l,0,sizeof l);
for(i=1;i<=n;i++)
{
scanf("%I64d",&v[i]);
l[i]=l[i-1]+v[i]+1;
if(l[i-1]<=v[i]) k=i;
}
for(i=k+1,r=0,b=0;i<=n;i++)
{
b+=(v[i]<=b);
r+=max(0ll,v[i]-b);
}
if((r+l[k-1])==v[k]) printf("%I64d\n",k);
else if((r+l[k-1])>v[k]) printf("Unknown\n");
else printf("Bad Rescue\n");
}
return 0;
}