[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;
}
posted @ 2021-03-14 19:21  liv_vil  阅读(75)  评论(0)    收藏  举报