题意:
N个村子连成一条线,相邻的村子相连(没有被摧毁)。三个命令:
D x,表示x村庄被摧毁;
Q x,表示与x直接或间接相连的村庄有多少个,当然包括他自己(被摧毁为0);
R,表示恢复最后被摧毁的村庄。
思路:
-
记录每个线段的从左边起的最大连续区间和从右边起的最大连续区间
-
如果在左边的最大连续区间 or 右边的最大连续区间,则return左边的最大连续区间 or 右边的最大连续区间(线段树的结点是1)
-
如果在左边的最大连续区间 or 右边的最大连续区间,则return左边的最大连续区间 + (结点-1)的右边的最大连续区间 or 右边的最大连续区间 + (结点+1)的左边的最大连续区间(线段树的结点不是1)
-
如果不在左边的最大连续区间 or 右边的最大连续区间,则递归找左子树 or 右子树
代码:
#include <iostream>
#define lson l, mid, pos << 1
#define rson mid + 1, r, pos << 1 | 1
using namespace std;
const int MAXN = 5e4 + 10;
struct node{
int sum; //该线段的长度(~len)
int l, r; //左边的最大连续区间, 右边的最大连续区间
}tree[MAXN<<2];
int a[MAXN], ai; //栈
void updata(int p){
tree[p].l = (tree[p<<1].l == tree[p<<1].sum) ? tree[p<<1].l + tree[p<<1|1].l : tree[p<<1].l;
tree[p].r = (tree[p<<1|1].r == tree[p<<1|1].sum) ? tree[p<<1|1].r + tree[p<<1].r : tree[p<<1|1].r;
}
void build(int l, int r, int pos){
if (l == r){
tree[pos].sum = tree[pos].l = tree[pos].r = 1;
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
updata(pos);
tree[pos].sum = tree[pos<<1].sum + tree[pos<<1|1].sum; //只更新1次
}
void add(int i, int v, int l, int r, int pos){
if (l == r){
tree[pos].l = tree[pos].r = v;
return;
}
int mid = (l + r) >> 1;
if (mid >= i)
add(i, v, lson);
else
add(i, v, rson);
updata(pos);
}
int find(int i, int l, int r, int pos){
if (l == r)
return 0;
if (pos == 1){
if (i - l + 1 <= tree[pos].l)
return tree[pos].l;
if (r - i + 1 <= tree[pos].r)
return tree[pos].r;
}
if (tree[pos].l && i - l + 1 <= tree[pos].l)
return tree[pos].l + tree[pos-1].r; // r<-pos-1 [ pos ]->l
if (tree[pos].r && r - i + 1 <= tree[pos].r)
return tree[pos].r + tree[pos+1].l; // r<-[ pos ] pos+1->l
int mid = (l + r) >> 1;
if (mid >= i)
return find(i, lson);
else
return find(i, rson);
}
int main(){
// freopen("_in.txt", "r", stdin);
// freopen("_out1.txt", "w", stdout);
int n, m, ans, b;
char op;
while (~scanf("%d%d", &n, &m)){
//一定要加while,不然会wa
ai = 0;
build(1, n, 1);
while (m--){
scanf(" %c", &op);
if (op == 'D'){
scanf("%d", &a[++ai]);
add(a[ai], 0, 1, n, 1);
}
else if (op == 'Q'){
scanf("%d", &b);
ans = find(b, 1, n, 1);
printf("%d\n", ans);
}
else
add(a[ai--], 1, 1, n, 1);
}
}
return 0;
}