题意:
初始 x x x值为 1 1 1,给定一个长度为 n n n的操作序列, ′ + ′ '+' ′+′表示 x = x + 1 x=x+1 x=x+1, ′ − ′ '-' ′−′表示 x = x − 1 x=x-1 x=x−1,再给定 m m m个询问,每次给定两个数 l , r l,r l,r,忽视从第 l l l到第 r r r这 r − l + 1 r-l+1 r−l+1个操作,问剩下的操作中可以得到不同数的个数。
数据范围: 1 ≤ n , m ≤ 2 × 1 0 5 , 1 ≤ l ≤ r ≤ n 1\leq n,m\leq 2\times 10^5,1\leq l\leq r\leq n 1≤n,m≤2×105,1≤l≤r≤n
题解:
考虑到这是一个连续操作,所以在一次操作序列中的所有操作,出现的数必然在 [ m i n , m a x ] [min,max] [min,max]之间,所以只需要每次找到区间 m i n min min和 m a x max max即可,记录一个前缀最大最小和后缀最大最小。
每次删除 [ l , r ] [l,r] [l,r]的操作相当于只操作 [ 1 , l − 1 ] [1,l-1] [1,l−1]和 [ r + 1 , n ] [r+1,n] [r+1,n],那么我们可以 O ( 1 ) O(1) O(1)得到 [ 1 , l − 1 ] [1,l-1] [1,l−1]的区间最大和最小, O ( 1 ) O(1) O(1)得到 [ r + 1 , n ] [r+1,n] [r+1,n]的区间最大最小,则得到了该区间由 s [ r ] s[r] s[r]上升的最大 u p up up和下降的最大 d o w n down down,之后再得到其由 a [ l − 1 ] a[l-1] a[l−1]上升 u p up up和由 a [ l − 1 ] a[l-1] a[l−1]下降 d o w n down down,即得到了真正的不操作 [ l , r ] [l,r] [l,r]序列的后的区间最大最小值。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>
inline T Read(){
T s = 0, f = 1; char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) {
s = (s << 3) + (s << 1) + ch - '0'; ch = getchar();}
return s * f;
}
#define read() Read<int>()
#define readl() Read<long long>()
const int N = 2e5 + 10;
const int INF = 0x3f3f3f3f;
char s[N];
int a[N];
int pmax[N], pmin[N], smax[N], smin[N];
int n, m, l, r;
void solve() {
scanf("%d%d", &n, &m);
scanf("%s", s + 1);
for(int i = 1, v = 0; i <= n; ++i) {
if(s[i] == '+') ++v;
else --v;
a[i] = v;
}
pmax[0] = pmin[0] = 0;
for(int i = 1; i <= n; ++i) {
pmax[i] = max(a[i], pmax[i - 1]);
pmin[i] = min(a[i], pmin[i - 1]);
}
smax[n + 1] = -INF, smin[n + 1] = INF;
for(int i = n; i >= 2; --i) {
smax[i] = max(smax[i + 1], a[i]);
smin[i] = min(smin[i + 1], a[i]);
}
while(m--) {
scanf("%d%d", &l, &r);
int lmax = pmax[l - 1], lmin = pmin[l - 1];
int rmax = smax[r + 1], rmin = smin[r + 1];
int res = 0;
if(rmax == -INF) {
res = lmax - lmin + 1;
}
else {
int up = rmax - a[r];
int down = a[r] - rmin;
int mx = max(lmax, a[l - 1] + up);
int mn = min(lmin, a[l - 1] - down);
res = mx - mn + 1;
}
printf("%d\n", res);
}
}
int main()
{
int T = 1;
scanf("%d", &T);
for(int i = 1; i <= T; ++i) solve();
return 0;
}