题意
定义长度m的数组b为good数组,如果对于1<=i<=m,有b[i]>=i。
给定长度为n的数组a。求a存在多少区间范围为[l,r]的子数组a[l],a[l+1], … , a[r-1], a[r],为good数组。1<=l<=r<=n,
其中1<=a[i]<=n
思路
双指针
定义起点下标i,终点下标j,
当存在第一个下标j,不满足a[j]>= (j-i+1)时,说明以i为初始下标,j为最终下标的数组不是good数组,
且以i为初始下标,长度小于j-i+1的都是good数组,
我们统计起来,并移动下标i。
代码实现很简洁明了。
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pcc pair<char, char>
#define inf 0x3f3f3f3f3f3f3f3f
const int maxn = 200010;
int n, a[maxn];
void solve() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
ll res = 0;
int i, j;
for (i = 1, j = 1; j <= n; ++j) {
while (j <= n && a[j] < (j - i + 1)) {
/*
arr1: a[i]
arr2: a[i], a[i+1]
...
arr_{j-i}: a[i], a[i+1], ..., a[j-1]
*/
res += j - i;
++i;
}
}
while (i < j) {
res += j - i;
++i;
}
printf("%lld\n", res);
}
int main() {
int t;
scanf("%d", &t);
// t = 1;
while (t--) {
solve();
}
}
/*
3
3
1 2 3
3
1 1 1
4
2 1 4 3
*/