题解:
模拟这个过程,对于每个点来说记录他的入度。
入度数组为 in,高度为 d
如果 in[i] >= (d - 1) 该点能由之前点来转化,而且多的可以更新下一个值 in[i + 1] += in[i] - (d - 1)
如果 in[i] < (d - 1) 那么他无法完全有之前的转换,得从该点开始, ans += (d - 1) - in[i]
然后对于该点来说更新他后面的点 j = (i + 2 ~ min(n, i + d[i])) 这个区间内的 in[j] ++
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
const int N = 100010;
int n;
ll z[N];
ll b[N];
int main(){
int _;
scanf("%d",&_);
while(_--) {
memset(b, 0, sizeof b);//初始化
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
scanf("%lld",&z[i]);
ll ans = 0;
for(int i = 1;i <= n;i ++) {
for(int j = 2;j <= z[i] && (i + j) <= n;j ++)
b[i + j] ++;
if(b[i] >=( z[i] - 1)) {
b[i + 1] += (b[i] - z[i] + 1);
}
else{
ans += (z[i] - b[i] - 1);
}
}
cout << ans << endl;
}
return 0;
}