题意:
有 n 个连续的村庄,m 次操作,每次操作分为三个,
- D x 表示 x 村庄被摧毁
- Q x 表示查询包含 x 村庄的最长连续长度
- R 表示修复最近一个被摧毁的村庄
对于第一个,如果村庄被摧毁,就直接进行单点修改,把该村庄的连续长度变为0,在返回的时候,就将对应区间的左连续和右连续改一下,左连续是左半区间的左连续,右连续是右半区间的右连续,一次向上更新即可
对于第二个,查询的话,如果这个当前区间的左连续包含这个点,输出左连续,如果包含在右连续区间内,输出右连续,如果都没有,看看是否包含在中间的连续区间内,如果包含在内,输出中间的连续区间,如果不在,就根据点的位置去查询左子树或右子树,重复上述过程,如果最后查到了对应的点,就输出点的连续情况即可
对于R操作,用一个栈(模拟栈)去存放被摧毁的信息,每次从栈顶取走一个,恢复即可,恢复的过程与破坏的过程思路一直,只是将连续恢复而已
因为本题目的更新过程只涉及单点更新,所以没必要采用标记下传的方法
#include <iostream>
#include <cstdio>
#include <stack>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stack>
using namespace std;
const int maxn = 50010;
int n, m, kk;
int st[maxn];
struct p{
int l, r, lsum, rsum, sum;
int getlen(){
return r - l + 1;
}
} c[maxn * 4];
void build(int l, int r, int k){
c[k].l = l;
c[k].r = r;
c[k].lsum = c[k].rsum = c[k].sum = c[k].getlen();
if(l == r){
return ;
}
int mid = (l + r) / 2;
build(l, mid, k * 2);
build(mid + 1, r, k * 2 + 1);
}
void update(int ind, int k, int d){// wrong
if(c[k].l == c[k].r){
c[k].lsum = c[k].rsum = c[k].sum = d;
return;
}
int mid = (c[k].l + c[k].r) / 2;
if(ind <= mid)update(ind, k * 2, d);
else update(ind, k * 2 + 1, d);
c[k].lsum = c[k * 2].lsum;
c[k].rsum = c[k * 2 + 1].rsum;
if(c[k * 2].lsum ==c[k * 2].getlen())c[k].lsum += c[k * 2 + 1].lsum;
if(c[k * 2 + 1].rsum == c[k * 2 + 1].getlen())c[k].rsum += c[k * 2].rsum;
c[k].sum = max(c[k].lsum, max(c[k].rsum, c[k * 2].rsum + c[k * 2 + 1].lsum));
}
int query(int ind, int k){
if(c[k].l == c[k].r) return c[k].lsum;
if(c[k].l <= ind && c[k].l + c[k].lsum - 1 >= ind)return c[k].lsum;
if(c[k].r >= ind && c[k].r - c[k].rsum + 1 <= ind)return c[k].rsum;
if(c[k * 2].r - c[k * 2].rsum + 1 <= ind && c[k * 2 + 1].l + c[k * 2 + 1].lsum - 1 >= ind)
return c[k * 2].rsum + c[k * 2 + 1].lsum;
int mid = (c[k].l + c[k].r) / 2;
if(ind <= mid)return query(ind, k * 2);
return query(ind, k * 2 + 1);
}
int main()
{
// freopen("in.txt", "r", stdin);
scanf("%d %d", &n, &m);
build(1, n, 1);
char op;
int x;
kk = 1;
for (int i = 1; i <= m; i++){
cin >> op;
if(op == 'D'){
scanf("%d", &x);
update(x, 1, 0);
st[kk++] = x;
}
else if(op == 'Q'){
scanf("%d", &x);
printf("%d\n",query(x, 1));
}
else if(op == 'R'){
if(kk >= 1){
x = st[--kk];
update(x, 1, 1);
}
}
}
return 0;
}