D. Program:Codeforces Round 102 (Rated for Div. 2)

D. Program

在这里插入图片描述

大致题意:

给你一个长为n的字符串 由‘+’、‘-’组成,初始值x=0,遇到+就+1,遇到-就-1。
给你m个询问,每一个询问存在两个整数l,r,问如果省略掉字符串中[l,r]的字符,x的不同值有多少个。

思路:

	首先,无论省略哪一块,x取值一定是连续的(原因:±1操作)。所以如果能知道最大值最小值,两者相减+1即可。
	其次,对于一连串操作,任何数经过这些操作所改变的上下起伏是一样的。
所以:
	对于最大值:在下标l之前的x最大值和r之后的所有操作起伏加上a[l-1]中取最大值。
	对于最小值:在下标l之前的x最小值和r之后的所有操作起伏加上a[l-1]中取最小值。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<cstdio>
#include<cmath>
#include<stdlib.h>

using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5+50;
int a[maxn];
int pmax[maxn],pmin[maxn];
int smax[maxn],smin[maxn];
void solve(){
	string s;
	int n,m;
	cin >> n >> m;
	cin >> s;
	int x = 0;
	a[0] = 0;
	//a[i]表示经过前i个字符后x的值 
	for(int i = 0;i < n;i++){
		if(s[i] == '+')	x++;
		else x--;
		a[i+1] = x;
	}
	pmax[0] = pmin[0] = 0;//未经过操作 初始值为0 
	smax[n+1] = -INF;smin[n+1] = INF;//临界 不会到此处 初始化为相应极值 
	for(int i = 1;i <= n;i++){
		pmax[i] = max(pmax[i-1],a[i]);
		pmin[i] = min(pmin[i-1],a[i]);
	}
	for(int i = n;i >= 1;i--){
		smax[i] = max(smax[i+1],a[i]);
		smin[i] = min(smin[i+1],a[i]);
	}
	int l,r;
	while(m--){
		cin >> l >> r;
		int ans = 0;
		int lmax = pmax[l-1],lmin = pmin[l-1];
		int rmax = smax[r+1],rmin = smin[r+1];
		if(r == n){//r在最后 起伏为0  直接lmax-lmin+1即可 
			ans = lmax-lmin+1;
			cout << ans << endl;
			continue;
		}
		int max_up = rmax-a[r],max_down = a[r]-rmin;//向上向下起伏波动 
		int rm = max(lmax,a[l-1]+max_up);
		int lm = min(lmin,a[l-1]-max_down);
		ans = rm-lm+1;
		cout << ans << endl;
	}
}
int main(){
	int t;
	cin >> t;
	while(t--){
		solve();
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值