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 }

 

 
posted @ 2019-08-11 12:40  滚烫的青春  阅读(211)  评论(0编辑  收藏  举报