Tunnel Warfare HDU - 1540 (线段树不同子树的合并)
在抗日战争期间,华北平原广大地区进行了大规模的隧道战。 一般来说,通过隧道连接的村庄排成一列。 除了两端,每个村庄都与两个相邻的村庄直接相连。
入侵者经常对一些村庄发动袭击并摧毁其中的部分隧道。 八路军指挥官要求最新的隧道和村庄连接状态。 如果某些村庄严重隔离,必须立即恢复连接!
Input
输入的第一行包含两个正整数n和m(n,m≤50,000),表示村庄和事件的数量。 接下来的m行中的每一行描述一个事件。
以下所示的不同格式描述了三种不同的事件:
D x:第x个村庄被毁。
Q x:指挥官询问第x个村庄与其直接或间接相关的村庄数量。
R:最后毁坏的村庄被重建了。
Output
按顺序输出每个指挥官询问的答案。
Sample Input
7 9
D 3
D 6
D 5
Q 4
Q 5
R
Q 4
R
Q 4
Sample Output
1
0
2
4
分析:
维护每个节点所对应区间的左最长1串,右最长一串和区间最长1串。查询的时候如果当前区间最长1串长度为0或者满,直接返回0\满;如果x位于当前区间的“中部”(左孩子的右和右孩子的左连接而成),直接返回中部长度;除此以外就继续查找。
代码:
1 #include <bits/stdc++.h>//题目也没说多组输入啊,WA了好多次,想哭 2 using namespace std; 3 const int maxn = 5 * 1e4 + 10; 4 struct node 5 { 6 int l, r; 7 int ln, rn, mn; 8 }t[maxn << 2]; 9 10 int n, m; 11 12 void pushup(int tar) 13 { 14 t[tar].ln = t[tar << 1].ln, t[tar].rn = t[tar << 1 | 1].rn; 15 t[tar].mn = max(t[tar << 1].mn, t[tar << 1 | 1].mn); 16 t[tar].mn = max(t[tar].mn, t[tar << 1].rn + t[tar << 1 | 1].ln); 17 if (t[tar << 1].ln == t[tar << 1].r - t[tar << 1].l + 1) t[tar].ln = t[tar << 1].ln + t[tar << 1 | 1].ln; 18 if (t[tar << 1 | 1].rn == t[tar << 1 | 1].r - t[tar << 1 | 1].l + 1) t[tar].rn = t[tar << 1 | 1].rn + t[tar << 1].rn; 19 } 20 21 void build(int l, int r, int tar) 22 { 23 t[tar].l = l, t[tar].r = r; 24 t[tar].ln = t[tar].rn = t[tar].mn = r - l + 1; 25 if (l == r) return; 26 int mid = (l + r) >> 1; 27 build(l, mid, tar << 1); 28 build(mid + 1, r, tar << 1 | 1); 29 } 30 31 void update(int x, int state, int tar) 32 { 33 if (t[tar].l == t[tar].r) 34 { 35 t[tar].ln = t[tar].rn = t[tar].mn = state; 36 return; 37 } 38 int mid = (t[tar].l + t[tar].r) >> 1; 39 if (x <= mid) update(x, state, tar << 1); 40 else if (x > mid) update(x, state, tar << 1 | 1); 41 pushup(tar); 42 } 43 44 int query(int x, int tar)//查询依据为,x必然存在于某个区间的中心部分,叶子节点除外,所以对叶子节点特判。 45 { 46 47 if (t[tar].l == t[tar].r) return 0;//如果是叶子节点直接输出0,说明48 int mid = (t[tar].l + t[tar].r) >> 1; 49 if (x >= t[tar << 1].r - t[tar << 1].rn + 1 && x <= t[tar << 1 | 1].l + t[tar << 1 | 1].ln - 1) return t[tar << 1].rn + t[tar << 1 | 1].ln; 50 else if (x <= mid) return query(x, tar << 1); 51 else return query(x, tar << 1 | 1); 52 } 53 54 int main() 55 { 56 int n, m; 57 58 while (cin >> n >> m) 59 { 60 stack<int> s; 61 char ope[2]; 62 int x; 63 64 build(1, n, 1); 65 while (m--) 66 { 67 cin >> ope; 68 if (ope[0] == 'D') 69 { 70 cin >> x; 71 s.push(x); 72 update(x, 0, 1); 73 } 74 else if (ope[0] == 'R') 75 { 76 x = s.top(); 77 s.pop(); 78 update(x, 1, 1); 79 } 80 else 81 { 82 cin >> x; 83 cout << query(x, 1) << endl; 84 } 85 } 86 } 87 }