题意:
题目定义了3种操作
D代表破坏村庄,
R代表修复最后被破坏的那个村庄,
Q代表询问包括x在内的最大连续区间是多少
思路:
和前面几道线段树的区间合并一样,在线段树的区间内,我们要用三个变量记录左边连续区间,右边连续区间和最大连续区间。
这题主要的难点是怎么查询。
我的查询函数是这么写的。
int query(int o, int L, int R, int pos) {
if(L == R) return 0;
int M = MID;
pushDown(o, L, R);
if(M - mxR[ls] + 1 <= pos && pos <= M + mxL[rs])
return mxR[ls] + mxL[rs];
else if(pos <= M) return query(lson, pos);
else return query(rson, pos);
}
判断当前的位置是否满足在左边连续和右边连续的区间之内。
如果满足返回当前该区间的长度,否则向下查找。
my code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define MID (L + R) >> 1
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls, L, M
#define rson rs, M+1, R
#define LEN(L, R) ((R) - (L) + 1)
using namespace std;
const int N = (int)5e4 + 10;
int n, m;
int mxL[N<<2], mxR[N<<2], mx[N<<2], cov[N<<2];
vector<int> vec;
int max(int a, int b, int c) {
return max(a, max(b, c));
}
void pushUp(int o, int L, int R) {
int M = MID;
mxL[o] = mxL[ls], mxR[o] = mxR[rs];
mx[o] = max(mx[ls], mx[rs], mxR[ls] + mxL[rs]);
if(mxL[ls] == LEN(L, M)) mxL[o] += mxL[rs];
if(mxR[rs] == LEN(M+1, R)) mxR[o] += mxR[ls];
if(cov[ls] == cov[rs]) cov[o] = cov[ls];
else cov[o] = -1;
}
void pushDown(int o, int L, int R) {
if(cov[o] != -1) {
int M = MID;
cov[ls] = cov[rs] = cov[o];
mxL[ls] = mxR[ls] = mx[ls] = cov[o] * LEN(L, M);
mxL[rs] = mxR[rs] = mx[rs] = cov[o] * LEN(M+1, R);
cov[o] = -1;
}
}
void build(int o, int L, int R) {
cov[o] = -1;
if(L == R) {
mxL[o] = mxR[o] = mx[o] = cov[o] = 1;
return ;
}
int M = MID;
build(lson);
build(rson);
pushUp(o, L, R);
}
void modify(int o, int L, int R, int pos, int val) {
if(L == R) {
mxL[o] = mxR[o] = mx[o] = cov[o] = val;
return ;
}
int M = MID;
pushDown(o, L, R);
if(pos <= M) modify(lson, pos, val);
else modify(rson, pos, val);
pushUp(o, L, R);
}
int query(int o, int L, int R, int pos) {
if(L == R) return 0;
int M = MID;
pushDown(o, L, R);
if(M - mxR[ls] + 1 <= pos && pos <= M + mxL[rs])
return mxR[ls] + mxL[rs];
else if(pos <= M) return query(lson, pos);
else return query(rson, pos);
}
int main() {
char op[10];
int ql, qr, x;
while(~scanf("%d%d", &n, &m)) {
build(1, 1, n);
vec.clear();
while(m--) {
scanf("%s", op);
if(op[0] == 'D') {
scanf("%d", &x);
vec.push_back(x);
modify(1, 1, n, x, 0);
}else if(op[0] == 'Q') {
scanf("%d", &x);
int ans = query(1, 1, n, x);
printf("%d\n", ans);
}else if(op[0] == 'R') {
x = vec.back();
vec.pop_back();
modify(1, 1, n, x, 1);
}
}
}
return 0;
}