[BZOJ 3083] 遥远的国度
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=3083
[算法]
树链剖分
时间复杂度 : O(NlogN ^ 2)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 #define MAXLOG 20 const int inf = 2e9; struct edge { int to , nxt; } e[MAXN << 1]; int n , q , tot , timer , rt; int a[MAXN] , head[MAXN] , dfn[MAXN] , l[MAXN] , r[MAXN] , fa[MAXN] , loc[MAXN] , son[MAXN] , size[MAXN] , top[MAXN] , depth[MAXN]; int up[MAXN][MAXLOG]; struct Segment_Tree { struct Node { int l , r; int value , tag; } Tree[MAXN << 2]; inline void update(int index) { Tree[index].value = min(Tree[index << 1].value , Tree[index << 1 | 1].value); } inline void pushdown(int index) { if (Tree[index].tag != -1) { Tree[index << 1].value = Tree[index << 1 | 1].value = Tree[index].tag; Tree[index << 1].tag = Tree[index << 1 | 1].tag = Tree[index].tag; Tree[index].tag = -1; } } inline void build(int index , int l , int r) { Tree[index].l = l; Tree[index].r = r; Tree[index].tag = -1; if (l == r) { Tree[index].value = a[loc[l]]; return; } int mid = (l + r) >> 1; build(index << 1 , l , mid); build(index << 1 | 1 , mid + 1 , r); update(index); } inline void modify(int index , int l , int r , int val) { if (Tree[index].l == l && Tree[index].r == r) { Tree[index].value = val; Tree[index].tag = val; return; } pushdown(index); int mid = (Tree[index].l + Tree[index].r) >> 1; if (mid >= r) modify(index << 1 , l , r , val); else if (mid + 1 <= l) modify(index << 1 | 1 , l , r , val); else { modify(index << 1 , l , mid , val); modify(index << 1 | 1 , mid + 1 , r , val); } update(index); } inline int query() { return Tree[1].value; } inline int query(int index , int l , int r) { if (l > r) return inf; if (Tree[index].l == l && Tree[index].r == r) return Tree[index].value; pushdown(index); int mid = (Tree[index].l + Tree[index].r) >> 1; if (mid >= r) return query(index << 1 , l , r); else if (mid + 1 <= l) return query(index << 1 | 1 , l , r); else return min(query(index << 1 , l , mid) , query(index << 1 | 1 , mid + 1 , r)); } } SGT; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void addedge(int u , int v) { ++tot; e[tot] = (edge){v , head[u]}; head[u] = tot; } inline void dfs1(int u , int father) { son[u] = 0; size[u] = 1; depth[u] = depth[father] + 1; up[u][0] = father; fa[u] = father; for (int i = 1; i < MAXLOG; i++) up[u][i] = up[up[u][i - 1]][i - 1]; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v == father) continue; dfs1(v , u); size[u] += size[v]; if (son[u] == 0 || size[v] > size[son[u]]) son[u] = v; } } inline void dfs2(int u , int t) { dfn[u] = l[u] = ++timer; loc[timer] = u; top[u] = t; if (son[u]) dfs2(son[u] , t); for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v != fa[u] && v != son[u]) dfs2(v , v); } r[u] = timer; } inline void modify(int u , int v , int w) { int tu = top[u] , tv = top[v]; while (tu != tv) { if (depth[tu] > depth[tv]) { swap(u , v); swap(tu , tv); } SGT.modify(1 , dfn[tv] , dfn[v] , w); v = fa[tv]; tv = top[v]; } if (dfn[u] > dfn[v]) swap(u , v); SGT.modify(1 , dfn[u] , dfn[v] , w); } int main() { read(n); read(q); for (int i = 1; i < n; i++) { int u , v; read(u); read(v); addedge(u , v); addedge(v , u); } for (int i = 1; i <= n; i++) read(a[i]); read(rt); dfs1(rt , 0); dfs2(rt , rt); SGT.build(1 , 1 , n); while (q--) { int type; read(type); if (type == 1) { int x; read(x); rt = x; } else if (type == 2) { int u , v , w; read(u); read(v); read(w); modify(u , v , w); } else { int x; read(x); if (x == rt) printf("%d\n" , SGT.query()); else if (l[x] <= l[rt] && r[x] >= r[rt]) { int y = rt; for (int i = MAXLOG - 1; i >= 0; i--) { if (depth[up[y][i]] > depth[x]) y = up[y][i]; } printf("%d\n" , min(SGT.query(1 , 1 , l[y] - 1) , SGT.query(1 , r[y] + 1 , n))); } else printf("%d\n" , SGT.query(1 , l[x] , r[x])); } } return 0; }