Educational Codeforces Round 102 (Rated for Div. 2) D(思维&线段树)

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.

 

题目大意:

给你一个数x,有n次操作,每个操作可以令x+1或者x-1,q次询问,每次询问你如果删除[l,r]的操作,x一共可以变成多少个数。

解法:

记max为过程中x可以成为的最大值,min为过程中x可以成为的最小值,答案就是max-min+1

如果没有询问,变成的最大值或最小值就可以通过前缀和来实现,现在多了删除连续的区间,就要算它带来的贡献。

假设删除的区间为[L,R],L之前的最大/小值和R之后的最大/小值都是可以通过线段树得到,不同的是,R之后的最大/小值要减去[L,R]的贡献即区间和才是删除后真正的最大/小值

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改宏定义!!!
}

 

&quot;educational codeforces round 103 (rated for div. 2)&quot;是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 &quot;educational codeforces round 103 (rated for div. 2)&quot;是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为&quot;educational&quot;,意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加&quot;educational codeforces round 103 (rated for div. 2)&quot;对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,&quot;educational codeforces round 103 (rated for div. 2)&quot;是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值