[CF]1491C - Pekora and Trampoline
https://codeforces.com/contest/1491/problem/C
从前往后做,当S[i]不为1时 把它变为1 用cnt[]记下它走到其他位置的次数
cnt[i]是指之前从1~i-1位置所有踩到i位置上的次数
如果S[i]不为1 :将S[i]减成1 要从i这里开始走max(1,S[i]-1)次 发现它会把所有i+2~min(s[i]+i,n)踩一次
如果S[i]为1 :跳到下一格。
所以如果之前走的过程中 把S[i]踩成1了 ,说明要把当S[i]=1以后踩的次数 加到cnt[i+1]
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=5010;
LL s[N];
LL cnt[N];
void solve()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
cnt[i]=0;
scanf("%lld",&s[i]);
}
LL ans=0;
for(int i=1;i<=n;i++)
{
if(s[i]-cnt[i]>1)//之前走的过程中 没有把这个位置的数变成1 要从i这个位置跳
{
ans+=s[i]-cnt[i]-1;//把i位置上的数减成1
cnt[i]=s[i]-1;//之前没有把S[i]变成1 所以cnt[i+1]不用加上cnt[i] 它不会拖累S[i+1]
}
for(int j=i+2;j<=min( n,i+s[i]);j++)cnt[j]++;
cnt[i+1]+=cnt[i]-(s[i]-1);//如果之前已走比S[i]-1大(之前已经把这个位置踩成1) 把次数累积给下一个
//因为S[i]已经被减成一 扛不住了 会跳到S[i+1]
}
printf("%lld\n",ans);
}
int main()
{
int tests=1;
scanf("%d",&tests);
// cin>>tests;
//while(~scanf("%d",&n))
while(tests--)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号