Description
捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩
捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋
子都互相可达。游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的
时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要
求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两
个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房
间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的
距离。
Input
第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,
表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如
上文所示。
Output
对于每一个操作Game,输出一个非负整数到hide.out,表示最远的两个关灯房间的距离。若只有一个房间是关
着灯的,输出0;若所有房间的灯都开着,输出-1。
Sample Input
1 2
2 3
3 4
3 5
3 6
6 7
6 8
7
G
C 1
G
C 2
G
C 1
G
Sample Output
3
3
4
HINT
对于100%的数据, N ≤100000, M ≤500000。
题解
博主吃鸡中...莫慌...一定补上...
1 //It is made by Awson on 2018.1.6 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <cstdio> 9 #include <string> 10 #include <vector> 11 #include <cstdlib> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 #define LL long long 16 #define RE register 17 #define lowbit(x) ((x)&(-(x))) 18 #define Max(a, b) ((a) > (b) ? (a) : (b)) 19 #define Min(a, b) ((a) < (b) ? (a) : (b)) 20 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b)) 21 using namespace std; 22 const int N = 100000; 23 const int M = 500000; 24 const int INF = ~0u>>1; 25 26 int n, m, u, v, fa[N+5], light[N+5]; 27 char ch[5]; 28 struct tt { 29 int to, next; 30 }edge[(N<<1)+5]; 31 int path[N+5], top; 32 void add(int u, int v) { 33 edge[++top].to = v; 34 edge[top].next = path[u]; 35 path[u] = top; 36 } 37 namespace LCA { 38 int bin[25], lim, dep[N+5], fa[N+5][25]; 39 void dfs(int o, int depth, int father) { 40 fa[o][0] = father, dep[o] = depth; 41 for (int i = path[o]; i; i = edge[i].next) 42 if (edge[i].to != father) dfs(edge[i].to, depth+1, o); 43 } 44 int query(int x, int y) { 45 if (dep[x] < dep[y]) Swap(x, y); 46 for (int i = lim; i >= 0; i--) if (dep[fa[x][i]] >= dep[y]) x = fa[x][i]; 47 if (x == y) return x; 48 for (int i = lim; i >= 0; i--) if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; 49 return fa[x][0]; 50 } 51 int dist(int x, int y) {return dep[x]+dep[y]-(dep[query(x, y)]<<1); } 52 void main() { 53 lim = log(n)/log(2), bin[0] = 1; for (int i = 1; i <= 20; i++) bin[i] = bin[i-1]<<1; 54 dfs(1, 1, 0); 55 for (int t = 1; t <= lim; t++) for (int i = 1; i <= n; i++) fa[i][t] = fa[fa[i][t-1]][t-1]; 56 } 57 } 58 struct heap { 59 priority_queue<int>q, p; 60 void pop() { 61 while (!q.empty() && !p.empty() && q.top() == p.top()) q.pop(), p.pop(); 62 q.pop(); 63 } 64 void erase(int val) {p.push(val); } 65 int top() { 66 while (!q.empty() && !p.empty() && q.top() == p.top()) q.pop(), p.pop(); 67 return q.top(); 68 } 69 int sec() { 70 while (!q.empty() && !p.empty() && q.top() == p.top()) q.pop(), p.pop(); 71 int tmp = q.top(); q.pop(); 72 while (!q.empty() && !p.empty() && q.top() == p.top()) q.pop(), p.pop(); 73 int val = q.top(); 74 q.push(tmp); return val; 75 } 76 int size() {return q.size()-p.size(); } 77 void push(int val) {q.push(val); } 78 }q1[N+5], q2[N+5], q3; 79 namespace Point_divide { 80 int size[N+5], mx[N+5], vis[N+5], root, minsize; 81 void get_size(int o, int fa) { 82 size[o] = 1, mx[o] = 0; 83 for (int i = path[o]; i; i = edge[i].next) 84 if (edge[i].to != fa && !vis[edge[i].to]) { 85 get_size(edge[i].to, o); 86 size[o] += size[edge[i].to]; 87 if (size[edge[i].to] > mx[o]) mx[o] = size[edge[i].to]; 88 } 89 } 90 void get_root(int o, int pa, int fa) { 91 mx[o] = Max(mx[o], size[pa]-size[o]); 92 if (mx[o] < minsize) minsize = mx[o], root = o; 93 for (int i = path[o]; i; i = edge[i].next) 94 if (edge[i].to != fa && !vis[edge[i].to]) get_root(edge[i].to, pa, o); 95 } 96 void get_dist(int o, int pa, int fa) { 97 q1[root].push(LCA::dist(pa, o)); 98 for (int i = path[o]; i; i = edge[i].next) 99 if (edge[i].to != fa && !vis[edge[i].to]) get_dist(edge[i].to, pa, o); 100 } 101 void work(int o, int pa) { 102 minsize = INF; get_size(o, 0), get_root(o, o, 0); 103 fa[root] = pa, vis[root] = 1; q2[root].push(0), q1[root].push(LCA::dist(pa, root)); 104 for (int i = path[root]; i; i = edge[i].next) 105 if (!vis[edge[i].to]) get_dist(edge[i].to, pa, root); 106 q2[pa].push(q1[root].top()); int rt = root; 107 for (int i = path[root]; i; i = edge[i].next) 108 if (!vis[edge[i].to]) work(edge[i].to, rt); 109 if (q2[rt].size() >= 2) q3.push(q2[rt].top()+q2[rt].sec()); 110 } 111 void main() {work(1, 0); } 112 } 113 114 void turnon(int o) { 115 if (q2[o].size() >= 2) q3.erase(q2[o].top()+q2[o].sec()); 116 q2[o].erase(0); 117 if (q2[o].size() >= 2) q3.push(q2[o].top()+q2[o].sec()); 118 for (int x = o; fa[x]; x = fa[x]) { 119 if (q2[fa[x]].size() >= 2) q3.erase(q2[fa[x]].top()+q2[fa[x]].sec()); 120 q2[fa[x]].erase(q1[x].top()); 121 q1[x].erase(LCA::dist(o, fa[x])); 122 if (q1[x].size()) q2[fa[x]].push(q1[x].top()); 123 if (q2[fa[x]].size() >= 2) q3.push(q2[fa[x]].top()+q2[fa[x]].sec()); 124 } 125 } 126 void turnoff(int o) { 127 if (q2[o].size() >= 2) q3.erase(q2[o].top()+q2[o].sec()); 128 q2[o].push(0); 129 if (q2[o].size() >= 2) q3.push(q2[o].top()+q2[o].sec()); 130 for (int x = o; fa[x]; x = fa[x]) { 131 if (q2[fa[x]].size() >= 2) q3.erase(q2[fa[x]].top()+q2[fa[x]].sec()); 132 if (q1[x].size()) q2[fa[x]].erase(q1[x].top()); 133 q1[x].push(LCA::dist(fa[x], o)); 134 q2[fa[x]].push(q1[x].top()); 135 if (q2[fa[x]].size() >= 2) q3.push(q2[fa[x]].top()+q2[fa[x]].sec()); 136 } 137 } 138 void work() { 139 scanf("%d" ,&n); 140 for (int i = 1; i < n; i++) { 141 scanf("%d%d", &u, &v); 142 add(u, v), add(v, u); 143 } 144 LCA::main(); Point_divide::main(); 145 int cnt = n; scanf("%d", &m); 146 while (m--) { 147 scanf("%s", ch); 148 if (ch[0] == ‘G‘) { 149 if (cnt <= 1) printf("%d\n", cnt-1); 150 else printf("%d\n", q3.top()); 151 }else { 152 scanf("%d", &u); 153 if (light[u]) turnoff(u), cnt++; 154 else turnon(u), cnt--; 155 light[u] ^= 1; 156 } 157 } 158 } 159 int main() { 160 work(); 161 return 0; 162 }