传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3083
这道题最重要的一点,树链剖分也是一种dfs序,于是我们记录时间戳,就既可以维护路径上的信息,也可以维护子树上的信息。
bzoj上倒数第三,-_-|||,然后看了身下的WJMZBMR,吓傻了。。。。。。
#include <iostream> #include <cstdio> #include <cstring> #include <list> #include <stack> #include <cmath> using namespace std; typedef long long LL; #define INF 1000000000000LL #define idx(l, r) ((l + r) | (l != r)) #define mid ((l + r) >> 1) const int maxn = 100010; struct node { int x, f; bool vis; node() {} node(int a, int b, bool c) { x = a; f = b; vis = c; } }; stack <node> q; list <int> edge[maxn]; int num[maxn], top[maxn], to[maxn], sz[maxn], dep[maxn], fa[maxn], rs[maxn]; int f[maxn][20]; LL a[maxn], mi[maxn * 2], lazy[maxn * 2]; int n, cnt, rt, tot, m; void get(int &tmp) { tmp = 0; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()); for(; ch >= '0' && ch <= '9'; ch = getchar()) tmp = tmp * 10 + ch - '0'; return; } void dfs() { q.push(node(rt, 0, false)); while(!q.empty()) { node t = q.top(); if(!t.vis) { q.top().vis = true; fa[t.x] = t.f; for(list <int> :: iterator p = edge[t.x].begin(); p != edge[t.x].end(); p ++) { if(*p == t.f) continue; dep[*p] = dep[t.x] + 1; q.push(node(*p, t.x, false)); } } else { for(list <int> :: iterator p = edge[t.x].begin(); p != edge[t.x].end(); p ++) { if(*p == t.f) continue; sz[t.x] += sz[*p]; if(!to[t.x] || sz[*p] > sz[to[t.x]]) to[t.x] = *p; } sz[t.x] ++; q.pop(); } } return; } void split() { q.push(node(rt, 0, false)); while(!q.empty()) { node t = q.top(); if(!t.vis) { q.top().vis = true; num[t.x] = ++tot; for(list <int> :: iterator p = edge[t.x].begin(); p != edge[t.x].end(); p ++) { if(*p == t.f || *p == to[t.x]) continue; top[*p] = *p; q.push(node(*p, t.x, false)); } if(to[t.x]) { top[to[t.x]] = top[t.x]; q.push(node(to[t.x], t.x, false)); } } else { rs[t.x] = tot; q.pop(); } } return; } void dfs2() { q.push(node(rt, 0, false)); while(!q.empty()) { node t = q.top(); if(!t.vis) { q.top().vis = true; if(!t.f) { for(int i = 0; i <= cnt; i ++) f[t.x][i] = t.x; } else { f[t.x][0] = t.f; for(int i = 1; i <= cnt; i ++) f[t.x][i] = f[f[t.x][i - 1]][i - 1]; } for(list <int> :: iterator p = edge[t.x].begin(); p != edge[t.x].end(); p ++) { if(*p == t.f) continue; q.push(node(*p, t.x, false)); } } else q.pop(); } return; } void go(int &x, int dd) { for(int i = 0; i <= cnt; i ++) { if((dd >> i) & 1) { x = f[x][i]; } } return; } int lca(int u, int v) { if(dep[u] < dep[v]) swap(u, v); go(u, dep[u] - dep[v]); for(int i = cnt; i >= 0; i --) { if(f[u][i] != f[v][i]) { u = f[u][i]; v = f[v][i]; } } if(u != v) { u = f[u][0]; v = f[v][0]; } return u; } void push_down(int l, int r) { if(!lazy[idx(l, r)]) return; mi[idx(l, r)] = lazy[idx(l, r)]; if(l < r) { lazy[idx(l, mid)] = lazy[idx(mid + 1, r)] = lazy[idx(l, r)]; } lazy[idx(l, r)] = 0; return; } void push_up(int l, int r) { push_down(l, mid); push_down(mid + 1, r); mi[idx(l, r)] = min(mi[idx(l, mid)], mi[idx(mid + 1, r)]); return; } void insert(int l, int r, int a, int b, LL d) { if(l > b || r < a) return; if(a <= l && r <= b) { mi[idx(l, r)] = d; lazy[idx(l, r)] = d; return; } push_down(l, r); insert(l, mid, a, b, d); insert(mid + 1, r, a, b, d); push_up(l, r); return; } LL ask(int l, int r, int a, int b) { if(a > b) return INF; if(l > b || r < a) return INF; push_down(l, r); if(a <= l && r <= b) return mi[idx(l, r)]; LL p = min(ask(l, mid, a, b), ask(mid + 1, r, a, b)); push_up(l, r); return p; } void update(int u, int v, LL d) { while(top[u] != top[v]) { if(dep[top[u]] < dep[top[v]]) swap(u, v); insert(1, n, num[top[u]], num[u], d); u = fa[top[u]]; } if(dep[u] > dep[v]) swap(u, v); insert(1, n, num[u], num[v], d); return; } int main() { scanf("%d%d", &n, &m); int u, v; for(int i = 1; i < n; i ++) { scanf("%d%d", &u, &v); edge[u].push_back(v); edge[v].push_back(u); } for(int i = 1; i <= n; i ++) { scanf("%lld", &a[i]); } scanf("%d", &rt); top[rt] = rt; dep[rt] = 1; dfs(); split(); cnt = (int)ceil(log2(n)); dfs2(); for(int i = 0; i < maxn * 2; i ++) mi[i] = INF; for(int i = 1; i <= n; i ++) { insert(1, n, num[i], num[i], a[i]); } int opt, id = rt; LL w; for(int i = 1; i <= m; i ++) { scanf("%d", &opt); if(opt == 1) { scanf("%d", &u); id = u; } else if(opt == 2) { scanf("%d%d%lld", &u, &v, &w); update(u, v, w); } else { scanf("%d", &u); int t = lca(u, id); if(u == id) { printf("%lld\n", ask(1, n, 1, n)); } else if(t == id) { printf("%lld\n", ask(1, n, num[u], rs[u])); } else if(t == u) { int p = id; go(p, dep[id] - dep[u] - 1); printf("%lld\n", min(ask(1, n, 1, num[p] - 1), ask(1, n, rs[p] + 1, n))); } else { printf("%lld\n", ask(1, n, num[u], rs[u])); } } } return 0; }