Luogu4116/SPOJ2798 Query on a tree III(Qtree3) 树链剖分

题目传送门: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 }

 

猜你喜欢

转载自www.cnblogs.com/Itst/p/9769723.html