Lab object -- 2013 noip day1 T3
We can solve this problem directly by multiplying the LCA .. However, I am a little confused .. Therefore, we use tree link splitting for this purpose.
Different from general vertex weights, for a tree, the vertex weights of each vertex are defined as the edge weights of his father. Therefore, compared with the general tree Chain Division, at last, 1 is added to the endpoint maintained by the line segment tree when it is unified to a chain .. Nothing else. Then pay attention to the comparison between Dep [UN [a] and Dep [UN [B] When the jump is up, not Dep [a] Dep [B];
# Include <iostream> # include <cstdio> # include <cstring> # include <algorithm> using namespace STD; const int MaxE = 100001; const int maxn = 100010; const int INF = 0x3f3f3f; struct line {int L, R, D;} s [MaxE]; struct edge {int T, D; edge * Next ;} E [maxn * 2], * head [maxn]; int Ne = 0; void addedge (int f, int T, int d) {e [NE]. T = T, E [NE]. D = D, E [NE]. next = head [f], head [f] = e + NE ++;} int int_get () {ch Ar c; int x = 0; C = (char) getchar (); While (! Isdigit (c) c = (char) getchar (); While (isdigit (c) {x = x * 10 + (INT) (C-'0 '); C = (char) getchar ();} return X;} int n, m; int father [maxn]; int find (int x) {return x = Father [x]? X: Find (father [x]);} bool CMP (line A, line B) {return. d> B. d;} int H [maxn], Fa [maxn], UN [maxn], map [maxn]; int W [maxn]; int size [maxn]; struct node {int key; node * l, * r;} se [maxn * 3], * root; int NS = 0; node * build (int l, int R) {node * Now = Se + NS ++; If (L ^ r) {int mid = (L + r)> 1; now-> L = build (L, mid); now-> r = build (Mid + 1, R);} return now;} void Update (node * X) {If (X-> L) x-> key = Min (X-> L-> key, X-> r-> key);} void insert (node * Now, int L, int R, int POs, int V) {If (L = r) now-> key = V; else {int mid = (L + r)> 1; if (Pos <= mid) insert (now-> l, l, mid, POs, V); else insert (now-> r, Mid + 1, R, POs, V ); update (now) ;}} int _ query (node * Now, int L, int R, int ls, int RS) {If (L = LS & R = RS) return now-> key; else {int mid = (L + r)> 1; if (RS <= mid) return _ q Uery (now-> l, l, mid, ls, RS); else if (LS> = Mid + 1) return _ query (now-> r, Mid + 1, r, ls, RS); else return min (_ query (now-> l, l, mid, ls, mid), _ query (now-> r, Mid + 1, r, Mid + 1, RS) ;}} void DFS (int x, int pre) {If (pre =-1) {H [x] = 1, fa [x] = x; W [x] = inf;} else h [x] = H [pre] + 1, Fa [x] = pre; size [x] = 1; for (edge * P = head [X]; P = p-> next) {If (! H [p-> T]) {DFS (p-> T, x); W [p-> T] = p-> D; size [x] + = size [p-> T] ;}} int tot = 0; void _ Union (int x, int pre) {If (pre =-1) UN [x] = x; else UN [x] = pre; Map [x] = ++ tot; insert (root, 1, n, map [X], W [x]); int Smax = 0; int Pos = 0; For (edge * P = head [X]; P; P = p-> next) {If (H [p-> T]> H [x]) {If (size [p-> T]> Smax) smax = size [p-> T], Pos = p-> T ;}} if (! Smax) return; else {_ Union (Pos, UN [x]); For (edge * P = head [X]; P = p-> next) {If (H [p-> T]> H [x] & P-> T! = POS) {_ Union (p-> T,-1) ;}}} void pre () {for (INT I = 1; I <= N; ++ I) Father [I] = I; sort (S + 1, S + 1 + M, CMP); int CNT = 0; For (INT I = 1; I <= M & CNT <= N; ++ I) {int FX = find (s [I]. l); int FY = find (s [I]. r); If (FX! = FY) {FATHER [FY] = FX; ++ CNT; addedge (s [I]. l, s [I]. r, s [I]. d); addedge (s [I]. r, s [I]. l, s [I]. d) ;}}void read () {n = int_get (), M = int_get (); For (INT I = 1; I <= m; ++ I) {s [I]. L = int_get (); s [I]. R = int_get (); s [I]. D = int_get () ;}root = build (1, N) ;}int q = 0; int query (int A, int B) {If (find ()! = Find (B) Return-1; int ret = inf; while (UN [a]! = UN [B]) {If (H [UN [a]> H [UN [B]) {int rs = map [a], ls = map [UN [a]; If (LS> RS) {A = Fa [UN [a]; continue;} ret = min (Ret, _ query (root, 1, n, ls, RS); a = Fa [UN [a];} else {int rs = map [B], ls = map [UN [B]; If (LS> RS) {B = Fa [UN [B]; continue;} ret = min (Ret, _ query (root, 1, n, ls, RS); B = Fa [UN [B] ;}} if (! = B) {If (H [a] <H [B]) Swap (a, B); int rs = map [a], ls = map [B] + 1; if (LS <= RS) {ret = min (Ret, _ query (root, 1, n, ls, RS) ;}return RET ;} void Sov () {pre (); For (INT I = 1; I <= N; ++ I) {If (! H [I]) {DFS (I,-1); _ Union (I,-1) ;}} q = int_get (); While (Q --) {int l, r; scanf ("% d", & L, & R); printf ("% d \ n", query (L, R ));}} int main () {// freopen ("test. in "," r ", stdin); read (); Sov (); Return 0 ;}