Program

题目链接:链接: codeforces—1473D.
题目描述:
You are given a program that consists of n instructions. Initially a single variable x is assigned to 0. Afterwards, the instructions are of two types:
increase x by 1;
decrease x by 1.
You are given m queries of the following format:
query l r — how many distinct values is x assigned to if all the instructions between the l-th one and the r-th one inclusive are ignored and the rest are executed without changing the order?

Input
The first line contains a single integer t (1≤t≤1000) — the number of testcases.
Then the description of t testcases follows.
The first line of each testcase contains two integers n and m (1≤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 n characters: each character is either ‘+’ or ‘-’ — increment and decrement instruction, respectively.
Each of the next m lines contains two integers l and r (1≤l≤r≤n) — the description of the query.
The sum of n over all testcases doesn’t exceed 2⋅105. The sum of m over all testcases doesn’t exceed 2⋅105.

Output
For each testcase print m integers — for each query l, r print the number of distinct values variable x is assigned to if all the instructions between the l-th one and the r-th one inclusive are ignored and the rest are executed without changing the order.

Example:
Input:
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:
1
2
4
4
3
3
4
2
3
2
1
2
2
2

题意:x的初始值为,给定长度为n的字符串,字符串中’+‘表示将x+1,’-'表示将x-1。进行m次操作,每次操作给出l,r;表示[l,r]区间内字符串内的字符操作取消,问在这种情况下x有多少个不同的值。

思路:
首先求出所有区间操作的前缀和sum[i],前缀和lp[i]表示[1,i]内最大的偏移R的范围,lm[i]表示[1,i]内最大偏移L的范围,同理rp[i],rm[i]表示后缀的[i,n]范围内的偏移关系。最后答案为计算操作的最大值减去最小值+1。
因为在计算x的最大、最小值时,要先计算[1,l-1]区间内的值,再计算[r+1,n]范围内的操作对x值的影响。而计算[r+1,n]时,可以只取[r+1,i](r+1<=i<=n)的rp值和lp值,所以需要进行如下操作:如果当前的指令是+让rp[i]=max(rp[i+1],0)+1,rm[i]=rm[i+1]+1;如果当前的指令是−让rp[i]=rp[i+1]−1,rm[i]=min(0,rm[i+1])−1;其中如果是+那么我肯定是要让rp[i]加一的但是因为可能rp[i]之前已经被减到<0了于是只好让他取个max当是−的时候同理。

#include<bits/stdc++.h>
#include<iostream>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
using namespace std;
typedef unsigned long long ull;
typedef  long long ll;
#define IOS std::ios::sync_with_stdio(false)
#define ls p<<1
#define rs p<<1|1
#define mod 1000000000 + 7
#define PI acos(-1.0)
#define INF   1e9
#define N 200000 + 5
/*********************Code*********************/
int t,n,m,lp[N],lm[N],rp[N],rm[N],sum[N];
char s[N];
int main(void){
    IOS;
    cin>>t;
    while(t--){
        cin>>n>>m>>s+1;
        sum[0] = lp[0] = lm[0] = rp[n+1] = rm[n+1] = 0;
        for(int i = 1;i <=n;i++){
            lp[i] = lp[i-1];
            lm[i] = lm[i-1];
            if(s[i]=='+')
                sum[i] = sum[i-1]+1;
            else
                sum[i] = sum[i-1]-1;
            lp[i] = max(lp[i],sum[i]);
            lm[i] = min(lm[i],sum[i]);
        }
        for(int i = n;i;i--){
            if(s[i]=='+')
                rp[i] = max(0,rp[i+1])+1,rm[i] =rm[i+1]+1;
            else
                rp[i] = rp[i+1]-1,rm[i] =min(0,rm[i+1])-1;
        }
        while(m--){
                int l,r,L,R;
            cin>>l>>r;
            L=lm[l-1];
            R=lp[l-1];
            L = min(L,sum[l-1]+rm[r+1]);
            R = max(R,sum[l-1]+rp[r+1]);
            cout<<R-L+1<<endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值