Educational Codeforces Round 102 (Rated for Div. 2) D (Thinking & Line Segment Tree)

You are given a program that consists of nn instructions. Initially a single variable xx is assigned to 00. Afterwards, the instructions are of two types:

  • increase xx by 11;
  • decrease xx by 11.

 

You are given mm queries of the following format:

  • query ll rr — how many distinct values is xx assigned to if all the instructions between the ll-th one and the rr-th one inclusive are ignored and the rest are executed without changing the order?

 

Input

The first line contains a single integer tt (1≤t≤10001≤t≤1000) — the number of testcases.

Then the description of tt testcases follows.

The first line of each testcase contains two integers nn and mm (1≤n,m≤2⋅1051≤n,m≤2⋅105) — the number of instructions in the program and the number of queries.

The second line of each testcase contains a program — a string of nn characters: each character is either '+' or '-' — increment and decrement instruction, respectively.

Each of the next mm lines contains two integers ll and rr (1≤l≤r≤n1≤l≤r≤n) — the description of the query.

The sum of nn over all testcases doesn't exceed 2⋅1052⋅105. The sum of mm over all testcases doesn't exceed 2⋅1052⋅105.

Output

For each testcase print mm integers — for each query ll, rr print the number of distinct values variable xx is assigned to if all the instructions between the ll-th one and the rr-th one inclusive are ignored and the rest are executed without changing the order.

Example

input

Copy

2
8 4
-+--+--+
1 8
2 8
2 5
1 1
4 10
+-++
1 1
1 2
2 2
1 3
2 3
3 3
1 4
2 4
3 4
4 4

output

Copy

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

Note

The instructions that remain for each query of the first testcase are:

  1. empty program — xx was only equal to 00;
  2. "-" — xx had values 00 and −1−1;
  3. "---+" — xx had values 00, −1−1, −2−2, −3−3, −2−2 — there are 44 distinct values among them;
  4. "+--+--+" — the distinct values are 11, 00, −1−1, −2−2.

 

Main idea:

Give you a number x, there are n operations, each operation can make x+1 or x-1, q times to ask, each time you are asked if you delete the operation of [l, r], how many numbers can x become? .

solution:

Let max be the maximum value that x can become during the process, and min be the minimum value that x can become during the process. The answer is max-min+1 .

If there is no query, the maximum or minimum value can be realized by prefix sum. Now if the continuous interval is deleted, the contribution brought by it is counted.

Assuming that the deleted interval is [L, R], the maximum/minimum value before L and the maximum/minimum value after R can be obtained through the line segment tree . The difference is that the maximum/minimum value after R is subtracted from [L , R]'s contribution is the interval sum is the true maximum/minimum value after deletion .

Accepted code

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;

#define sc scanf
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pir pair <int, int>
#define MK(x, y) make_pair(x, y)
#define MEM(x, b) memset(x, b, sizeof(x))
#define MPY(x, b) memcpy(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int Mod = 1e9 + 7;
const int N = 2e5 + 100;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % Mod; b >>= 1; t = (t*t) % Mod; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }

int mx[N * 4], mi[N * 4];
int pre[N], n, m;
char s[N];

#define ls (o << 1)
#define rs (ls | 1)
void Build(int o, int L, int R) {
	if (L == R) 
		mx[o] = mi[o] = pre[L];
	else {
		int mid = (L + R) >> 1;
		Build(ls, L, mid), Build(rs, mid + 1, R);
		mx[o] = max(mx[ls], mx[rs]);
		mi[o] = min(mi[ls], mi[rs]);
	}
}
int Ask_Mx(int o, int L, int R, int l, int r) {
	if (L >= l && R <= r)
		return mx[o];
	else {
		int mid = (L + R) >> 1, ans = -INF;
		if (mid >= l)
			Max(ans, Ask_Mx(ls, L, mid, l, r));
		if (mid < r)
			Max(ans, Ask_Mx(rs, mid + 1, R, l, r));
		return ans;
	}
}
int Ask_Mi(int o, int L, int R, int l, int r) {
	if (L >= l && R <= r)
		return mi[o];
	else {
		int mid = (L + R) >> 1, ans = INF;
		if (mid >= l)
			Min(ans, Ask_Mi(ls, L, mid, l, r));
		if (mid < r)
			Min(ans, Ask_Mi(rs, mid + 1, R, l, r));
		return ans;
	}
}

int main()
{
#ifdef OlaMins
	freopen("D:/input.txt", "r", stdin);
	//freopen("D:/output.txt", "w", stdout);
#endif

	int T; cin >> T;
	while (T--) {
		sc("%d %d %s", &n, &m, s + 1);
		for (int i = 1; i <= n; i++) 
			pre[i] = pre[i - 1] + (s[i] == '+' ? 1 : -1);  // 前缀和
		Build(1, 1, n);

		while (m--) {
			int l, r, mx1 = 0, mi1 = 0;
			sc("%d %d", &l, &r);

			if (l > 1) {
				Max(mx1, Ask_Mx(1, 1, n, 1, l - 1));   // L之前的答案可以直接得到
				Min(mi1, Ask_Mi(1, 1, n, 1, l - 1));
			}
			if (r < n) {    // R之后的答案要减去区间LR的贡献
				Max(mx1, Ask_Mx(1, 1, n, r + 1, n) - pre[r] + pre[l - 1]);
				Min(mi1, Ask_Mi(1, 1, n, r + 1, n) - pre[r] + pre[l - 1]);
			}

			printf("%d\n", mx1 - mi1 + 1);
		}
	}
	return 0; // 改数组大小!!!用pair改宏定义!!!
}

 

Guess you like

Origin blog.csdn.net/weixin_43851525/article/details/112981850