题目链接在这里
题目大意:
一条直线上有n个连续的村庄,对村庄有m个操作,操作有3种:
D x,将x村庄摧毁
Q x,询问和x村(包括它自己)相连的村长有多少个
R 恢复最后一个被摧毁的村庄
思路分析:
用线段树保存村庄的状态
在叶子中维护三个变量:llong, rlong, midlong(名字是我瞎起的),分别代表左端点开始有多少个村庄相连、从右端点开始有多少个村庄相连、在这一段中最多有多少个村庄连续。
可以看出,llong的大小就是左孩子的llong大小,如果左孩子的没有被摧毁的村庄(即tree [ lchild ]. llong == tree [ lchild ]. r - tree [ lchild ]. l + 1 ),那还要加上右孩子的llong。
rlong同理。
midlong的大小就是在左孩子的midlong、右孩子的midlong、左孩子的rlong + 右孩子的llong三者之间取一个最大的。
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <stack>
#define rep(i, n) for(int i = 0; i < n; ++i)
#define clr(x) memset(x, 0, sizeof(x))
#define rl (rt << 1)
#define rr (rt << 1 | 1)
using namespace std;
const int MaxN = 5e4 + 10;
struct Node{
int l, r, mid;
int llong, rlong, midlong;
}tree[MaxN << 2];
int n, m;
void build(int l, int r, int rt){
tree[rt].l = l;
tree[rt].r = r;
tree[rt].mid = (l + r) >> 1;
tree[rt].llong = tree[rt].rlong = tree[rt].midlong = r - l + 1;
if(l == r) return;
build(l, tree[rt].mid, rl);
build(tree[rt].mid + 1, r, rr);
}
void update(int rt, int pos, int w){
if(tree[rt].l == tree[rt].r){
tree[rt].llong = tree[rt].rlong = tree[rt].midlong = w;
return;
}
if(pos <= tree[rt].mid)
update(rl, pos, w);
else
update(rr, pos, w);
tree[rt].midlong = max(tree[rl].rlong + tree[rr].llong, max(tree[rl].midlong, tree[rr].midlong));
tree[rt].llong = tree[rl].llong == tree[rl].r - tree[rl].l + 1 ? tree[rl].llong + tree[rr].llong : tree[rl].llong;
tree[rt].rlong = tree[rr].rlong == tree[rr].r - tree[rr].l + 1 ? tree[rr].rlong + tree[rl].rlong : tree[rr].rlong;
int query(int rt, int pos){
if(tree[rt].l == tree[rt].r || tree[rt].midlong == tree[rt].r - tree[rt].l + 1 || tree[rt].midlong == 0)
return tree[rt].midlong;
if(pos <= tree[rt].mid){
if(pos >= tree[rt].mid - tree[rl].rlong + 1)
return tree[rl].rlong + tree[rr].llong;
else
query(rl, pos);
}
else{
if(pos <= tree[rt].mid + tree[rr].llong)
return tree[rl].rlong + tree[rr].llong;
else
query(rr, pos);
}
}
int main(){
while(~scanf("%d %d", &n, &m)){
getchar();
stack<int> sta;
int x;
char c;
build(1, n, 1);
while(m--){
c = getchar();
if(c == 'D'){
scanf("%d", &x);
sta.push(x);
update(1, x, 0);
}
else if(c == 'Q'){
scanf("%d", &x);
printf("%d\n", query(1, x));
}
else{
update(1, sta.top(), 1);
sta.pop();
}
getchar();
}
}
return 0;
}