【cf1473d Program】 线段树区间查询
题意
我们有一个x,初始为0,我们按字符串顺序进行“+1”或“-1”操作。有m个询问,每次询问我们删去字符串的l到r的符号后,x在完成所有操作中出现的不同数值的总数(包括初始的0)。
思路
因为每次只能进行+-1,所以从a到b必然会经过a到b所有的整数。我们可以用线段树记录下区间的最大和最小值,然后查询删去中间后分开的前面和后面两个部分。后面的部分可以减去经过第r个操作的x和第l个操作之前的x的差。之后就可以通过这两个范围来得出结果。
AC代码
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <functional>
using namespace std;
typedef long long ll;
const int MAXN = 200005;
const int INF = 1e9+7;
typedef struct tree{
int tmax;
int tmin;
} tree;
tree stree[MAXN << 2]; //线段树
int num[MAXN]; //原数组
void stree_push_up(int k){ //向上更新
stree[k].tmax = max(stree[k << 1].tmax, stree[k << 1 | 1].tmax);
stree[k].tmin = min(stree[k << 1].tmin, stree[k << 1 | 1].tmin);
}
void stree_build(int k,int l,int r){ //建树
if(l==r){
stree[k].tmax = num[l]; stree[k].tmin = num[l];
}
else{
int mid = l + ((r - l) >> 1);
stree_build(k << 1, l, mid);
stree_build(k << 1 | 1, mid + 1, r);
stree_push_up(k);
}
}
tree stree_query(int a,int b,int k,int l,int r){ //区间查询
if(a<=l&&b>=r) return stree[k];
int mid = l + ((r - l) >> 1);
tree res;
res.tmax = -INF; res.tmin = INF;
if(a<=mid){
tree tmp = stree_query(a, b, k << 1, l, mid);
res.tmax = max(tmp.tmax, res.tmax);
res.tmin = min(tmp.tmin, res.tmin);
}
if(b>mid){
tree tmp = stree_query(a, b, k << 1 | 1, mid + 1, r);
res.tmax = max(tmp.tmax, res.tmax);
res.tmin = min(tmp.tmin, res.tmin);
}
return res;
}
char c[MAXN];
int main(){
int t;
scanf("%d", &t);
while(t--){
int n, m;
scanf("%d %d",&n,&m);
getchar();
scanf("%s", c);
int x = 0;
num[1] = 0;
for (int i = 2; i <= n+1;i++){
if(c[i-2]=='+') x++;
else x--;
num[i] = x;
}
stree_build(1, 1, n+1);
while(m--){
int a, b;
scanf("%d %d", &a, &b);
tree f = stree_query(1, a, 1, 1, n + 1);
if(b+2<=n+1){
tree q = stree_query(b+2, n+1, 1, 1, n + 1);
q.tmax += num[a] - num[b + 1];
q.tmin += num[a] - num[b + 1];
f.tmax = max(f.tmax, q.tmax);
f.tmin = min(f.tmin, q.tmin);
}
int sum = f.tmax - f.tmin + 1;
printf("%d\n", sum);
}
}
return 0;
}

浙公网安备 33010602011771号