C1. Good Subarrays (Easy Version)

C1. Good Subarrays (Easy Version)

This is the easy version of this problem. In this version, we do not have queries. Note that we have multiple test cases in this version. You can make hacks only if both versions of the problem are solved.

An array $b$ of length $m$ is good if for all $i$ the $i$-th element is greater than or equal to $i$. In other words, $b$ is good if and only if $b_i \leq i$ for all $i$ ($1 \leq i \leq m$).

You are given an array $a$ consisting of $n$ positive integers. Find the number of pairs of indices $(l,r)$, where $1 \leq l \leq r \leq n$, such that the array $[a_l,a_{l+1}, \dots ,a_r]$ is good.

Input

Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \leq t \leq 2 \cdot {10}^{5}$). Description of the test cases follows.

The first line of each test case contains an integer $n$ ($1 \leq n \leq 2 \cdot {10}^{5}$), the length of the array $a$.

The second line of each test case contains $n$ space-separated integers $a_1,a_2, \dots ,a_n (1 \leq a_i \leq n)$, representing the array $a$.

It is guaranteed that the sum of $n$ over all test cases does not exceed $2 \cdot {10}^{5}$.

Output

For each test case, print the number of suitable pairs of indices.

Example

input

3
3
1 2 3
3
1 1 1
4
2 1 4 3

output

6
3
7

Note

In the first test case, all subarrays of $a$ are good, so all pairs are suitable.

In the second test case, the pairs $(1,1)$, $(2,2)$, and $(3,3)$ are suitable. For example, when $(l,r)=(1,2)$, the array $b=[1,1]$ is not good because $b_2<2$.

 

解题思路

  比赛的时候是写线段树过的。先说一下思路,首先对于每一个下标$i$,看看它最左可以到达哪里,这个下标位置就是$p_i = min\{ {i - a_i + 1, 1} \}$。然后在区间$[p_i, i]$中,可能会存在某些位置能到达最左边的下标位置会大于$p_i$,因此要在区间$[p_i, i -1]$中找到最大的$p_j, \, (j \in [p_i, i -1])$,那么$[p_j, i]$就是以下标$i$为结尾能够向左取到满足要求的最长的子数组。

  因为涉及到区间求最值问题,因此可以用线段树来维护各个区间的最大值。

  AC代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 2e5 + 10;
 7 
 8 int a[N];
 9 struct Node {
10     int l, r, maxv;
11 }tr[N * 4];
12 
13 void build(int u, int l, int r) {
14     if (l == r) {
15         tr[u] = {l, r, max(1, l - a[l] + 1)};
16     }
17     else {
18         int mid = l + r >> 1;
19         build(u << 1, l, mid);
20         build(u << 1 | 1, mid + 1, r);
21         tr[u] = {l, r, max(tr[u << 1].maxv, tr[u << 1 | 1].maxv)};
22     }
23 }
24 
25 int query(int u, int l, int r) {
26     if (tr[u].l >= l && tr[u].r <= r) return tr[u].maxv;
27     int mid = tr[u].l + tr[u].r >> 1, ret = 0;
28     if (l <= mid) ret = query(u << 1, l, r);
29     if (r >= mid + 1) ret = max(ret, query(u << 1 | 1, l, r));
30     return ret;
31 }
32 
33 void solve() {
34     int n;
35     scanf("%d", &n);
36     for (int i = 1; i <= n; i++) {
37         scanf("%d", a + i);
38     }
39     build(1, 1, n);
40     LL ret = 0;
41     for (int i = 1; i <= n; i++) {
42         int t = query(1, max(1, i - a[i] + 1), i);    // 求区间[p[j], i]中的最大的p[j]
43         ret += i - t + 1;    // 最大长度子数组区间就是[p[j], i]
44     }
45     printf("%lld\n", ret);
46 }
47 
48 int main() {
49     int t;
50     scanf("%d", &t);
51     while (t--) {
52         solve();
53     }
54     
55     return 0;
56 }

  实际上并没有这么复杂,可以用双指针来实现。

  假设以$i$为结尾满足要求的子数组最靠左能到达的位置是$j$,这时$i$往后移动到达$i'$,对应的最靠左能够到达的位置是$j'$,同时有${j'} < j$。这意味着在区间$k \in [{j'}, i]$中,所有位置$k$均满足$a_k \geq k - {j'} + 1 > k - j + 1$,即对于$i$来说最靠左能到达的位置可以是${j'}$,这就矛盾了。因此当$i$往右移动时,指针$j$也是往右移动,因此两个指针具有单调性,可以用双指针。

  AC代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 2e5 + 10;
 7 
 8 int a[N];
 9 
10 void solve() {
11     int n;
12     scanf("%d", &n);
13     for (int i = 1; i <= n; i++) {
14         scanf("%d", a + i);
15     }
16     LL ret = 0;
17     for (int i = 1, j = 1; i <= n; i++) {
18         while (a[i] < i - j + 1) {
19             j++;
20         }
21         ret += i - j + 1;
22     }
23     printf("%lld\n", ret);
24 }
25 
26 int main() {
27     int t;
28     scanf("%d", &t);
29     while (t--) {
30         solve();
31     }
32     
33     return 0;
34 }

 

参考资料

  Codeforces Round #825 (Div. 2) Editorial:https://codeforces.com/contest/1736

posted @ 2022-10-11 16:08  onlyblues  阅读(144)  评论(0编辑  收藏  举报
Web Analytics