2243: [sdoi2011] dyeing time limit: 20 sec memory limit: 512 MB
Submit: 1861 solved: 739
[Submit] [Status] Description
Given a rootless tree with N nodes and M operations, there are two types of operations:
1. color all vertices from node A to Node B to C;
2. Ask about the number of color segments from node A to Node B (the same segment is regarded as continuous color). For example, "112221" consists of three segments: "11", "222", and "1 ".
Please write a program to complete the M operations in sequence.
Input
The first line contains two integers n and M, indicating the number of nodes and the number of operations respectively;
The second line contains n positive integers to indicate the initial color of N nodes.
Each line below contains two integers x and y, indicatingXAndYThere is a undirected edge between them.
Each line below describes an operation:
"C a B c" indicates that this is a dyeing operation. All vertices (including a and B) from node A to Node B are colored C;
"Q a B" indicates that this is an inquiry operation. It queries the number of color segments from node A to Node B (including a and B.
Output
Output a line of answers for each query operation.
Sample input6 5
2 2 1 2 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
Sample output3
1
2
Hint
Number n <= 10 ^ 5, operand m <= 10 ^ 5, all colors C are integers and between [0, 10 ^ 9.
Source
Day1 in the first round
Solution: Tree links are divided to maintain information using a line segment tree. The focus is to merge two line segments.
Assume it is 11211333 3321122
A seg records the leftmost color, rightmost color, answer, and three values.
The merge statement is seg [RT]. ans = seg [RT <1]. ans + seg [RT <1 | 1]. ans-(SEG [RT <1]. R = seg [RT <1 | 1]. l );
There is a trick, the color is [^ 9], so pay attention to ~, Refer when marking the move
Note that the answers should be dynamically merged.
Let's talk about the line segments you have extracted. Imagine the whole process is the process of moving X and Y to the LCA, then, the two values are used to record the colors at the top side of X and the colors at the top side of Y respectively. In the last step, we just need to judge the specific value of LCA.
/* 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 = 100010; int edge, N, Fa [maxn], SZ [maxn], son [maxn], DEP [maxn], hash [maxn], top [maxn]; int H [maxn], num, a [maxn], X, Y, TX, Ty, Q, Col, ANS, LCOL, rcol; char s [22]; struct EDG E {int to, Ne;} e [maxn * 2]; struct seg {int ans, L, R, same; void clear () {ans = L = r = same = 0 ;}} 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; son [k] = 0; Dep [k] = Dep [from] + 1; for (int p = H [k]; P! =-1; P = E [p]. ne) {int to = E [p]. to; If (from = to) continue; Fa [to] = K; DFS (to, k); SZ [k] + = SZ [to]; if (SZ [to]> SZ [son [k]) Son [k] = to;} void build (int K, int from) {hash [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 (! = Fa [k] &! = Son [k]) Build (to, to) ;}// {segment part void pushup (int rt) {seg [RT]. L = seg [RT <1]. l; seg [RT]. R = seg [RT <1 | 1]. r; seg [RT]. ans = seg [RT <1]. ans + seg [RT <1 | 1]. ans-(SEG [RT <1]. R = seg [RT <1 | 1]. l);} void same (int rt, int col) {seg [RT]. same = Col; seg [RT]. L = seg [RT]. R = Col; seg [RT]. ans = 1;} 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, int 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);} seg query (int l, int R, int L, int R, int RT) {If (L <= L & R <= r) {return seg [RT];} int mid = (L + r)> 1; seg ans,, b; ans. clear ();. Clear (); B. clear (); Pushdown (RT); If (L <= mid) A = query (L, R, lson); If (Mid + 1 <= r) B = query (L, R, rson); ans. ans =. ans + B. ans; ans. L =. l; ans. R = B. r; If (B. L = 0) ans. R =. r; if (. L = 0) ans. L = B. l; If (B. l! = 0 & A. L! = 0) {ans. ans-= (. R = B. l);} pushup (RT); Return ans;} // }}// void work () {Tx = top [X]; ty = top [y]; while (TX! = Ty) {If (DEP [TX] <Dep [ty]) {swap (TX, Ty); swap (x, y);} change (hash [TX], hash [X], Col, 1, n, 1); X = Fa [TX]; Tx = top [X];} if (DEP [x]> Dep [y]) Swap (x, y); change (hash [X], hash [Y], Col, 1, n, 1);} int get_ans () {ans = 0; Tx = top [X]; ty = top [y]; LCOL = rcol = 0; while (TX! = Ty) {If (DEP [TX] <Dep [ty]) {seg Haha = query (hash [ty], hash [Y], 1, n, 1 ); // printf ("Ty: % d y: % d LCOL: % d rcol: % d l: % d r: % d haha. ans: % d \ n ", Ty, Y, LCOL, rcol, haha. l, haha. r, haha. ans); ans + = haha. ans; If (haha. R = rcol) ans --; rcol = haha. l; y = Fa [ty]; ty = top [y];} else {seg Haha = query (hash [TX], hash [X], 1, n, 1); // printf ("TX: % d x: % d LCOL: % d rcol: % d l: % d r: % d haha. ans: % d \ n ", TX, X, LCOL, rcol, haha. l, haha. r, haha. ans); ans + = haha. ans; If (haha. R = LCOL) ans --; LCOL = haha. l; X = Fa [TX]; Tx = top [x] ;}} if (DEP [x]> Dep [y]) {seg Haha = query (hash [Y], hash [X], 1, n, 1); // printf ("Y: % d x: % d rcol: % d haha. r: % d haha. ans: % d \ n ", Y, X, rcol, haha. r, haha. ans); ans + = haha. ans; If (haha. R = LCOL) ans --; If (haha. L = rcol) ans --;} else {seg Haha = query (hash [X], hash [Y], 1, n, 1); // printf ("X: % d y: % d LCOL: % d haha. r: % d haha. ans: % d \ n ", X, Y, LCOL, haha. r, haha. ans); ans + = haha. ans; If (haha. R = rcol) ans --; If (haha. L = LCOL) ans --;} // puts (""); Return ans;} void Init () {scanf ("% d", & N, & Q); For (INT I = 1; I <= N; I ++) {scanf ("% d", & A [I]); A [I] ++;} memset (H,-1, sizeof (h); For (INT I = 1; I <= n-1; I ++) {scanf ("% d", & X, & Y); addedge (x, y); addedge (Y, x);} DFS (1, 0 ); build (1, 1); For (INT I = 1; I <= N; I ++) Change (hash [I], hash [I], a [I], 1, n, 1);/* For (INT I = 1; I <= N; I ++) {printf ("I: % d top: % d hash: % d \ n ", I, top [I], hash [I]);} */while (Q --) {scanf (" % S % d ", s, & X, & Y); If (s [0] = 'C') {scanf ("% d", & col); Col ++; work (); continue;} printf ("% d \ n", get_ans () ;}} int main () {Init (); close (); Return 0 ;}