3083: Time Limit: 10 sec memory limit: 128 MB in distant countries
Submit: 839 solved: 192
[Submit] [Status] Description
Description
Zcwwzdjn in the pursuit of very Sb zhx, and zhx escaped into a distant country. When zcwwzdjn is ready to enter a distant country to continue to chase, the patron saint rapid blocked zcwwzdjn's path, he needs zcwwzdjn to complete the task before entering the distant country to continue to chase.
The problem is that there are n cities in a distant country, which are connected by several roads and constitute a tree. There is a capital in this country. We can regard this capital as the root of the entire tree. However, far away countries are strange that the capital may change to another city at any time. Each city in a distant country has a defense value. Sometimes, rapid changes the defense value of all cities on the path between two cities to a certain value. Rapid wants to know the minimum defense value of all cities in which the capital is regarded as the root of the entire tree. Because rapid cannot solve this problem, he stopped zcwwzdjn and hoped he could help. However, zcwwzdjn still needs to chase the zhx OF Sb, so this major problem is handed over to you.
Input
Two integers n m in the row 1st represent the number of cities and the number of operands.
Line 2 to line N, each line has two integers u v, representing a path between City U and City v.
Line n + 1 has n integers representing the initial defense value of all vertices.
An integer ID in line N + 2, representing the initial capital ID.
Line N + 3 to line N + m + 2 has an integer opt first. If opt = 1, then an integer ID indicates that the capital is changed to ID; if opt = 2, then there are three integers P1 P2 V, which means to change the defense value of all cities in the P1 P2 path to V; if opt = 3, next there is an integer ID that represents the minimum defense value in the subtree with the city id as the root.
Output
For each opt = 3 operation, the output line represents the minimum vertex weight of the corresponding subtree.
Sample input3 7
1 2
1 3
1 2 3
1
3 1
2 1 1 6
3 1
2 2 2 5
3 1
2 3 3 4
3 1
Sample output1
2
3
4
Prompt
For 20% of data, n <= 1000 m <= 1000.
For another 10% of data, n <= 100000, m <= 100000, make sure to change to a single point of modification.
For another 10% of data, n <= 100000, m <= 100000 ensures that the tree is a chain.
For another 10% of data, n <= 100000, m <= 100000, there is no operation to modify the capital.
For 100% of data, n <= 100000, m <=, 0 <ownership value <= 2 ^ 31. Hintsource
Zhonghaoxi
Orz Zhong Shen's question, this question has a root change operation, but think carefully, in fact, it does not "affect" the DFS Sequence
Tree link partitioning also produces a valid DFS order. For root replacement, the default root node is 1.
Assuming that the root is root, only the answers from the root to the 1 path will be affected, and the remaining points will be the query subtree.
As for the points in the root to 1 path, we found that after the root is changed, the queried range is (this is a bit difficult to describe)
Upload the image
The query point is X.
In addition to the subtree in the red circle, the other points are the points I want to query, that is, the point closest to X in the root to 1 path, if the DFS sequence is continuous, You can query the completion set.
The modification is a period, so just mark it.
Note that root = x is the entire subtree.
/* Author: wuw.jun */# include <cstdio> # include <cstring> # include <cstdlib> # include <algorithm> # define lson L, mid, RT <1 # define rson Mid + 1, R, RT <1 | 1 using namespace STD; typedef long ll; typedef double dd; const int maxn = 200010; const ll INF = (LL) 1e14 + 9; int H [maxn], n, m, top [maxn], LCA [maxn] [21], son [maxn], edge, SZ [maxn], DEP [maxn]; int L [maxn], R [maxn], root, num, X, Y, TX, Ty, T, OP T; ll Val, a [maxn]; struct edge {int to, Ne;} e [maxn * 2]; struct seg {ll Minn, same ;} SEG [maxn <2]; void close () {exit (0);} void addedge (int x, int y) {e [edge]. to = y; E [edge]. ne = H [X]; H [x] = edge ++;} void DFS (int K, int from) {SZ [k] = 1; dep [k] = Dep [from] + 1; son [k] = 0; For (int p = H [k]; P! =-1; P = E [p]. ne) {int to = E [p]. to; If (to = from) continue; LCA [to] [0] = K; For (INT I = 1; I <= 20; I ++) LCA [to] [I] = LCA [LCA [to] [I-1] [I-1]; DFS (to, k); SZ [k] + = SZ [to]; if (SZ [to]> SZ [son [k]) Son [k] = to;} void build (int K, int from) {L [k] = ++ num; top [k] = from; If (son [k]) Build (son [K], from ); for (int p = H [k]; P! =-1; P = E [p]. Ne) {int to = E [p]. To; If (! = LCA [k] [0] &! = Son [k]) Build (to, to);} R [k] = num;} int get_lca (int x, int y) {If (DEP [x] <Dep [y]) Swap (x, y); int depth = Dep [x]-dep [y]; for (INT I = 20; i> = 0; I --) if (depth & (1 <I) x = LCA [x] [I]; If (x = y) return X; for (INT I = 20; I> = 0; I --) {If (LCA [x] [I]! = LCA [y] [I]) {x = LCA [x] [I]; y = LCA [y] [I] ;}} return LCA [x] [0];} void pushup (int rt) {seg [RT]. minn = min (SEG [RT <1]. minn, SEG [RT <1 | 1]. minn);} void same (int rt, ll Val) {seg [RT]. minn = val; seg [RT]. same = val;} void Pushdown (int rt) {If (SEG [RT]. same) {same (RT <1, SEG [RT]. same); same (RT <1 | 1, SEG [RT]. same); seg [RT]. same = 0 ;}} void change (int l, int R, ll Val, int L, int R, int RT) {If (L <= L & R <= r) {same (RT, Val); return;} int mid = (L + r)> 1; Pushdown (RT ); if (L <= mid) Change (L, R, Val, lson); If (Mid + 1 <= r) Change (L, R, Val, rson ); pushup (RT);} ll query (int l, int R, int L, int R, int RT) {If (L> r) return INF; if (L <= L & R <= r) {return seg [RT]. minn;} int mid = (L + r)> 1; Pushdown (RT); LL ans = inf; If (L <= mid) ans = min (ANS, query (L, R, lson); If (Mid + 1 <= r) ans = Min (ANS, query (L, R, rson); pushup (RT); Return ans;} void CC () {Tx = top [x]; ty = top [y]; while (TX! = Ty) {If (DEP [TX] <Dep [ty]) {swap (x, y); swap (TX, Ty);} change (L [TX], L [X], Val, 1, n, 1); X = LCA [TX] [0]; Tx = top [X];} if (DEP [x] <Dep [y]) Swap (x, y); change (L [Y], L [X], Val, 1, n, 1);} void work () {If (root = x) {printf ("% LLD \ n", SEG [1]. minn); // query the global return;} t = get_lca (root, x); If (T! = X) // It indicates that it is not in the root path {printf ("% LLD \ n", query (L [X], R [X], 1, n, 1); return;} int depth = Dep [root]-dep [x]-1; int Haha = root; For (INT I = 20; I> = 0; I --) if (depth & (1 <I) Haha = LCA [Haha] [I]; printf ("% LLD \ n", min (query (1, L [Haha]-1, 1, n, 1), query (R [Haha] + 1, n, 1, n, 1);} void Init () {scanf ("% d", & N, & M); memset (H,-1, sizeof (h); For (INT I = 1; I <= n-1; I ++) {scanf ("% d", & X, & Y); addedge (x, y); addedge (Y, x) ;}for (INT I = 1; I <= N; I ++) scanf ("% LLD", & A [I]); DFS (1, 0); Build (1, 1);/* For (INT I = 1; I <= N; I ++) printf ("I: % d top: % d hash: % d son: % d \ n ", I, top [I], L [I], son [I]); close (); */For (INT I = 1; I <= N; I ++) Change (L [I], L [I], a [I], 1, n, 1); scanf ("% d", & root); While (M --) {scanf ("% d", & OPT); If (OPT = 1) scanf ("% d", & root); If (OPT = 2) {scanf ("% d % LLD", & X, & Y, & Val ); CC () ;}if (OPT = 3) {scanf ("% d", & X); Work () ;}} int main () {Init (); close (); Return 0 ;}