题意:有n个村庄,m个事件。村庄一开始是从小到大连续的,有三种操作
(1)D a为摧毁第a个村庄。
(2)Q a为询问与第a个村子直接和间接相连的村子有多少个。
(3)R 为恢复最近销毁的那个村庄
思路:难得想的是询问操作,恢复操作用一个栈保存就可以了。
#include <iostream> #include <cstdio> #include <cstring> #include <stack> using namespace std; #define maxn 100009 #define lson left,mid,rt<<1 #define rson mid+1,right,rt<<1|1 struct node { int lmx, rmx; } sum[maxn << 2]; void push_up(int rt, int left, int right) { sum[rt].lmx = sum[rt << 1].lmx; sum[rt].rmx = sum[rt << 1 | 1].rmx; int mid = (left + right) >> 1; if(sum[rt << 1].lmx == mid - left + 1) sum[rt].lmx += sum[rt << 1 | 1].lmx; if(sum[rt << 1 | 1].rmx == right - mid) sum[rt].rmx += sum[rt << 1].rmx; } void build(int left, int right, int rt) { if(left == right) { sum[rt].lmx = sum[rt].rmx = 1; return ; } int mid = (left + right) >> 1; build(lson); build(rson); push_up(rt, left, right); } void update(int pos, int val, int left, int right, int rt) { if(left == right) { if(val == -1) sum[rt].lmx = sum[rt].rmx = 0; if(val == 1) sum[rt].lmx = sum[rt].rmx = 1; return ; } int mid = (left + right) >> 1; if(pos <= mid) update(pos, val, lson); else update(pos, val, rson); push_up(rt, left, right); } void query(int pos, int &s, int &e, int left, int right, int rt) { if(left == right) { if(sum[rt].lmx == 1) s = e = left; else s = e = 0; return ; } int mid = (left + right) >> 1; if(pos <= mid) query(pos, s, e, lson); else query(pos, s, e, rson); if(mid == e) e += sum[rt << 1 | 1].lmx; if(mid == s) s -= sum[rt << 1].rmx; } int main() { int n, m; int a; while(scanf("%d%d", &n, &m) != EOF) { stack<int>st; build(1, n, 1); while(m--) { int s, e; char c[5]; scanf("%s", c); if(c[0] == 'D') { scanf("%d", &a); update(a, -1, 1, n, 1); st.push(a); } else if(c[0] == 'Q') { scanf("%d", &a); query(a, s, e, 1, n, 1); printf("%d ", e - s); } else { a = st.top(); st.pop(); update(a, 1, 1, n, 1); } } } return 0; }