BZOJ 3083 - 遥远的国度
原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3083
说话间又一个多月过去了。。该来除除草了,每天都是训练、没效率,训练、没效率。。省选考得不好不说了=-继续努力吧
题目大意:维护一棵有根树,支持三个操作:换根; 一条链上都改为一个值; 求某个子树的Min
算法分析:
裸的动态树问题,非常简单啦。只涉及链上和子树操作,树的形态没有改变,所以用剖分来搞。就按照最开始给定的那个根剖分,得到一个剖分序。在换根之后查子树的时候注意一件事情,就是在最早的定根的形态中,现在的根如果在要查询的那个子树的根的某个儿子的子树上的话,就需要查询整个树除去这个儿子的子树的最小值,否则就是原来的那个子树的最小值。至于怎么判断,我用剖分序乱搞的=-
参考代码:
1 //date 20140521 2 #include <cstdio> 3 #include <cstring> 4 5 const int maxn = 105000; 6 const int INF = 0x7FFFFFFF; 7 8 template <typename T> inline void swap(T &a, T &b){T x = a; a = b; b = x;} 9 inline int innew(int &a, int b){if(a < b){a = b; return 1;} return 0;} 10 inline int denew(int &a, int b){if(a > b){a = b; return 1;} return 0;} 11 inline int min(int a, int b){return a < b ? a : b;} 12 13 inline int getint() 14 { 15 int ans(0); char w = getchar(); 16 while(w < '0' || '9' < w) w = getchar(); 17 while('0' <= w && w <= '9') 18 { 19 ans = ans * 10 + w - '0'; 20 w = getchar(); 21 } 22 return ans; 23 } 24 25 int n, m, root; 26 struct edge 27 { 28 int v, next; 29 }E[maxn << 1]; 30 int nedge, a[maxn], num[maxn]; 31 32 inline void add(int u, int v) 33 { 34 E[++nedge].v = v; 35 E[nedge].next = a[u]; 36 a[u] = nedge; 37 } 38 39 int dpt[maxn], p[maxn], size[maxn], hp[maxn], hs[maxn]; 40 int order[maxn], ps[maxn], ped[maxn]; 41 42 inline void dfs_one(int v0) 43 { 44 static int d[maxn], now[maxn]; 45 int last, i, j; 46 memcpy(now, a, sizeof a); 47 d[last = dpt[v0] = size[v0] = 1] = v0; 48 while(last) 49 { 50 if(!(j = now[i = d[last]])) 51 { 52 if((--last) && (size[d[last]] += size[i], size[hs[d[last]]] < size[i])) 53 hs[d[last]] = i; 54 continue; 55 } 56 if(p[i] != E[j].v) dpt[d[++last] = E[j].v] = dpt[p[E[j].v] = i] + (size[E[j].v] = 1); 57 now[i] = E[j].next; 58 } 59 } 60 61 inline void dfs_two(int v0) 62 { 63 static int d[maxn], now[maxn]; 64 int last, i, j, tot; 65 d[last = 1] = order[ps[v0] = ped[v0] = tot = 1] = v0; 66 memset(now, 0xFF, sizeof now); 67 for(int i = 1; i <= n; ++i) hp[i] = i; 68 while(last) 69 { 70 if(!(j = now[i = d[last]])) 71 { 72 if(--last) innew(ped[d[last]], ped[i]); 73 continue; 74 } 75 if(j == -1) 76 { 77 if(hs[i]) hp[d[++last] = order[ps[hs[i]] = ped[hs[i]] = ++tot] = hs[i]] = hp[i]; 78 now[i] = a[i]; continue; 79 } 80 if(E[j].v != hs[i] && E[j].v != p[i]) d[++last] = order[ps[E[j].v] = ped[E[j].v] = ++tot] = E[j].v; 81 now[i] = E[j].next; 82 } 83 } 84 85 struct Segment_Tree 86 { 87 struct node 88 { 89 node *s[2]; 90 int l, r, Min, cov; 91 node(){} 92 int cover(int v){Min = v; cov = 1;} 93 void pushdown() 94 { 95 if(cov && l < r){s[0]->cover(Min); s[1]->cover(Min);} 96 cov = 0; 97 } 98 void update(){ Min = min(s[0]->Min, s[1]->Min);} 99 }*root, pond[maxn << 1]; 100 int stop; 101 102 void change(node *p, int l, int r, int v) 103 { 104 if(l <= p->l && p->r <= r){p->cover(v); return;} 105 p->pushdown(); 106 int mid = (p->l + p->r) >> 1; 107 if(l <= mid) change(p->s[0], l, r, v); 108 if(r > mid) change(p->s[1], l, r, v); 109 p->update(); 110 } 111 112 int query(node *p, int l, int r) 113 { 114 if(l <= p->l && p->r <= r){return p->Min;} 115 p->pushdown(); 116 int mid = (p->l + p->r) >> 1; 117 int ans = INF; 118 if(l <= mid) denew(ans, query(p->s[0], l, r)); 119 if(r > mid) denew(ans, query(p->s[1], l, r)); 120 return ans; 121 } 122 123 node *build(int l, int r) 124 { 125 node *p = &pond[stop++]; 126 p->s[0] = p->s[1] = NULL; p->cov = 0; p->l = l; p->r = r; 127 if(l == r) {p->Min = num[order[l]]; return p;} 128 int mid = (l + r) >> 1; 129 p->s[0] = build(l, mid); 130 p->s[1] = build(mid + 1, r); 131 p->update(); 132 return p; 133 } 134 135 void preset(){stop = 0; root = build(1, n);} 136 137 int get_min(int l, int r) 138 { 139 if(l > r) swap(l, r); 140 return query(root, l, r); 141 } 142 143 void change(int l, int r, int v) 144 { 145 if(l > r) swap(l, r); 146 change(root, l, r, v); 147 } 148 }MEOW; 149 150 inline void reroot(int r){root = r;} 151 inline void change(int x, int y, int v) 152 { 153 int x0 = x, y0 = y; 154 while(hp[x0] != hp[y0]) 155 { 156 if(dpt[hp[x0]] > dpt[hp[y0]]) 157 { 158 MEOW.change(ps[hp[x0]], ps[x0], v); 159 x0 = p[hp[x0]]; 160 }else{ 161 MEOW.change(ps[hp[y0]], ps[y0], v); 162 y0 = p[hp[y0]]; 163 } 164 } 165 MEOW.change(ps[x0], ps[y0], v); 166 } 167 inline int query(int x) 168 { 169 if(x == root) return MEOW.root->Min; 170 int x0 = x, r = root, sgn = 1, tp = 0; 171 if(hp[x0] == hp[r] && dpt[r] > dpt[x]) sgn = 0; 172 while(hp[x0] != hp[r]) 173 { 174 if(dpt[hp[x0]] > dpt[hp[r]]) {sgn = 1; break;} 175 if(p[hp[r]] == x0) tp = hp[r]; 176 sgn = 0; r = p[hp[r]]; 177 } 178 if(dpt[r] < dpt[x]) sgn = 1; 179 if(sgn) return MEOW.get_min(ps[x], ped[x]); 180 if(r != x0) tp = hs[x0]; 181 int ans = MEOW.get_min(1, ps[tp] - 1); 182 if(ped[tp] != n) denew(ans, MEOW.get_min(ped[tp] + 1, n)); 183 return ans; 184 } 185 186 int main() 187 { 188 freopen("bzoj.in", "r", stdin); 189 freopen("bzoj.out", "w", stdout); 190 191 n = getint(); m = getint(); 192 for(int i = 1; i < n; ++i) 193 { 194 int x = getint(), y = getint(); 195 add(x, y); add(y, x); 196 } 197 for(int i = 1; i <= n; ++i) num[i] = getint() - 1; 198 root = getint(); 199 dfs_one(root); dfs_two(root); 200 MEOW.preset(); 201 for(int i = 1; i <= m; ++i) 202 { 203 int k, x, y, v; 204 k = getint(); 205 switch(k) 206 { 207 case 1: x = getint(); reroot(x); break; 208 case 2: x = getint(); y = getint(); v = getint() - 1; change(x, y, v); break; 209 case 3: x = getint(); printf("%u\n", (unsigned)query(x) + 1u); break; 210 } 211 } 212 return 0; 213 }