题意:给定含有n个整数的数组a,找出所有满足这个条件的区间个数:[l,l+1,l+2……r],使得对于第i个位置上的元素,bi>=i(本文后面我们叫这样的区间为V)
假设有一个这样的数组:
样例一:
1, 2, 3, 4……
我们令c[i]为前i个数含有的V区间个数,那么对应的
c[1]=1
c[2]=c[1]+2=3
c[3]=c[2]+3=6
c[4]=c[3]+4=10
样例二:
1,2,1,4……
我们令c[i]为前i个数含有的V区间个数,那么对应的
c[1]=1
c[2]=c[1]+2=3
c[3]=c[2]+1=4
c[4]=c[3]+2=6
注意这里为什么不一样
先分析样例一:
对于a[4]=4,包含4的区间一共有4个
4,
3,4
2,3,4
1,2,3,4
不包括a[4]的有6个(这个6是根据a[1]~a[3]得到的)
那么c[4]=c[3]+4=10就是这样得到的
再分析样例二:
对于a[4]=4,包含4的区间一共有2个
4
1,4
不包括a[4]的有4个(这个6是根据a[1]~a[3]得到的)
那么c[4]=c[3]+2=6就是这样得到的
所以问题简化为,对于第i个数a[i],我们只需要求c[i-1]+包含a[i]的区间个数,包含a[i]的区间必须以a[i]为结尾
在两个样例中,在4往前走的时候,如果为3,那么还可以继续往前走;但是如果为1,就不能往前走了,因为题目中要求的第i个位置是的元素必须大于等于i,如果此时为1,那么它只能位于一个区间的第一个位置。所以第一个样例可以一直走到最前面(走了3步),含有4个满足条件的区间;第二个样例只能往前走1步,含有2两个满足条件的区间
每往前走一步,那么包含a[i]的区间就加一
所以可以得到c[i]=c[i-1]+min(id[i], a[i], d[i-1]+1)
第二个加式表示在前i个数里,包含a[i]的区间个数,记为d[i]
即min(自身下标,自身的值,包含a[i-1]的V区间个数+1)
1、我们需要考虑不能一直往前,也就是小于等于它的下标
2、需要小于等于它自身的值
3、包含a[i-1]的V区间个数,加上它自己形成的一个V区间,也即d[i-1]+1
为了避免超时,我们可以把d[i]记录下来,当到i+1的时候,直接使用就行
#include <bits/stdc++.h>
using namespace std;
#define de(x) cout<<x<<" ";
#define Pu puts("");
#define sf(x) scanf("%d",&x);
typedef long long ll;
const int N=2e5+10,mod=100003;
const int inf=0x3f3f3f3f;
int a[N];
ll c[N];
int d[N];
int n,m;
int main(){
int T;cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=n;i++){
sf(a[i])
}
c[1]=1;
d[1]=1;
for(int i=2;i<=n;i++){
d[i]=min(i,min(a[i],d[i-1]+1));
c[i]=d[i]+c[i-1];
}
printf("%lld\n",c[n]);
}
}