题目传送门:https://www.luogu.org/problemnew/show/P4116
题意:给出一个$N$个节点的树,树点有黑白两种颜色,$Q$次操作,支持转换某个点颜色与查询从$1$号节点到某个点的路径上第一个白点的编号。
然而又是树剖裸题
线段树记录链上最浅的白色节点即可
1 #include<bits/stdc++.h>
2 #define MAXN 100001
3 using namespace std;
4
5 namespace IO{
6 const int maxn((1 << 21) + 1);
7 char ibuf[maxn], *iS, *iT, obuf[maxn], *oS = obuf, *oT = obuf + maxn - 1, c, st[55];
8 int f, tp;
9 char Getc() {
10 return (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, maxn, stdin), (iS == iT ? EOF : *iS++)) : *iS++);
11 }
12 void Flush() {
13 fwrite(obuf, 1, oS - obuf, stdout);
14 oS = obuf;
15 }
16 void Putc(char x) {
17 *oS++ = x;
18 if (oS == oT) Flush();
19 }
20 template <class Int> void Input(Int &x) {
21 for (f = 1, c = Getc(); c < '0' || c > '9'; c = Getc()) f = c == '-' ? -1 : 1;
22 for (x = 0; c <= '9' && c >= '0'; c = Getc()) x = (x << 3) + (x << 1) + (c ^ 48);
23 x *= f;
24 }
25 template <class Int> void Print(Int x) {
26 if (!x) Putc('0');
27 if (x < 0) Putc('-'), x = -x;
28 while (x) st[++tp] = x % 10 + '0', x /= 10;
29 while (tp) Putc(st[tp--]);
30 }
31 void Getstr(char *s, int &l) {
32 for (c = Getc(); c < 'a' || c > 'z'; c = Getc());
33 for (l = 0; c <= 'z' && c >= 'a'; c = Getc()) s[l++] = c;
34 s[l] = 0;
35 }
36 void Putstr(const char *s) {
37 for (int i = 0, n = strlen(s); i < n; ++i) Putc(s[i]);
38 }
39 }
40 using namespace IO;
41
42 struct node{
43 int l , r , minN;
44 }Tree[MAXN << 2];
45 struct Edge{
46 int end , upEd;
47 }Ed[MAXN << 1];
48 int son[MAXN] , size[MAXN] , fa[MAXN] , dep[MAXN] , head[MAXN];
49 int top[MAXN] , ind[MAXN] , rk[MAXN] , N , cntEd , ts;
50
51 inline void addEd(int a , int b){
52 Ed[++cntEd].end = b;
53 Ed[cntEd].upEd = head[a];
54 head[a] = cntEd;
55 }
56
57 void dfs1(int dir , int father){
58 size[dir] = 1;
59 dep[dir] = dep[fa[dir] = father] + 1;
60 for(int i = head[dir] ; i ; i = Ed[i].upEd)
61 if(!dep[Ed[i].end]){
62 dfs1(Ed[i].end , dir);
63 size[dir] += size[Ed[i].end];
64 if(size[son[dir]] < size[Ed[i].end])
65 son[dir] = Ed[i].end;
66 }
67 }
68
69 void dfs2(int dir , int t){
70 top[dir] = t;
71 rk[ind[dir] = ++ts] = dir;
72 if(!son[dir])
73 return;
74 dfs2(son[dir] , t);
75 for(int i = head[dir] ; i ; i = Ed[i].upEd)
76 if(Ed[i].end != son[dir] && Ed[i].end != fa[dir])
77 dfs2(Ed[i].end , Ed[i].end);
78 }
79
80 inline int min(int a , int b){
81 return a < b ? a : b;
82 }
83
84 void init(int dir , int l , int r){
85 Tree[dir].l = l;
86 Tree[dir].r = r;
87 if(l == r)
88 Tree[dir].minN = 999999;
89 else{
90 init(dir << 1 , l , (l + r) >> 1);
91 init(dir << 1 | 1 , ((l + r) >> 1) + 1 , r);
92 Tree[dir].minN = min(Tree[dir << 1].minN , Tree[dir << 1 | 1].minN);
93 }
94 }
95
96 void change(int dir , int tar){
97 if(Tree[dir].l == Tree[dir].r){
98 Tree[dir].minN = Tree[dir].minN == 999999 ? Tree[dir].l : 999999;
99 return;
100 }
101 if(tar <= (Tree[dir].l + Tree[dir].r) >> 1)
102 change(dir << 1 , tar);
103 else
104 change(dir << 1 | 1 , tar);
105 Tree[dir].minN = min(Tree[dir << 1].minN , Tree[dir << 1 | 1].minN);
106 }
107
108 int findMin(int dir , int l , int r){
109 if(Tree[dir].l >= l && Tree[dir].r <= r)
110 return Tree[dir].minN;
111 int minN;
112 if(l <= (Tree[dir].l + Tree[dir].r) >> 1){
113 minN = findMin(dir << 1 , l , r);
114 if(minN != 999999)
115 return minN;
116 }
117 if(r > (Tree[dir].l + Tree[dir].r) >> 1)
118 return findMin(dir << 1 | 1 , l , r);
119 return 999999;
120 }
121
122 inline int work(int tar){
123 int minN = 999999;
124 while(top[tar] != 1){
125 minN = min(minN , findMin(1 , ind[top[tar]] , ind[tar]));
126 tar = fa[top[tar]];
127 }
128 minN = min(minN , findMin(1 , 1 , ind[tar]));
129 return minN == 999999 ? -1 : rk[minN];
130 }
131
132 int main(){
133 int N , M;
134 Input(N);
135 Input(M);
136 for(int i = 1 ; i < N ; i++){
137 int a , b;
138 Input(a);
139 Input(b);
140 addEd(a , b);
141 addEd(b , a);
142 }
143 dfs1(1 , 0);
144 dfs2(1 , 1);
145 init(1 , 1 , N);
146 while(M--){
147 int a;
148 Input(a);
149 if(a == 0){
150 Input(a);
151 change(1 , ind[a]);
152 }
153 else{
154 Input(a);
155 Print(work(a));
156 Putc('\n');
157 }
158 }
159 Flush();
160 return 0;
161 }