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 bii for all i (1im).

You are given an array a consisting of n positive integers. Find the number of pairs of indices (l,r), where 1lrn, such that the array [al,al+1,,ar] is good.

Input

Each test contains multiple test cases. The first line contains the number of test cases t (1t2105). Description of the test cases follows.

The first line of each test case contains an integer n (1n2105), the length of the array a.

The second line of each test case contains n space-separated integers a1,a2,,an(1ain), representing the array a.

It is guaranteed that the sum of n over all test cases does not exceed 2105.

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 b2<2.

 

解题思路

  比赛的时候是写线段树过的。先说一下思路,首先对于每一个下标i,看看它最左可以到达哪里,这个下标位置就是pi=min{iai+1,1}。然后在区间[pi,i]中,可能会存在某些位置能到达最左边的下标位置会大于pi,因此要在区间[pi,i1]中找到最大的pj,(j[pi,i1]),那么[pj,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[j,i]中,所有位置k均满足akkj+1>kj+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 @   onlyblues  阅读(152)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示