# BZOJ3531 [Sdoi2014]旅行

  1 /**************************************************************
2     Problem: 3531
3     User: rausen
4     Language: C++
5     Result: Accepted
6     Time:7692 ms
7     Memory:170268 kb
8 ****************************************************************/
9
10 #include <cstdio>
11 #include <algorithm>
12
13 using namespace std;
14 const int N = 100005;
15 const int M = 10000005;
16
17 struct edge {
18     int next, to;
19     edge() {}
20     edge(int _n, int _t) : next(_n), to(_t) {}
21 } e[N << 1];
22
23 struct tree_node {
24     int fa, son;
25     int dep, sz, top, w;
26 } tr[N];
27 int cnt_tree;
28
29 struct segment_node {
30     int mx, sum, lson, rson;
31 } seg[M];
32 int cnt_seg;
33
34 int n;
35 int first[N], tot;
36 int root[N], c[N], w[N];
37
39     int x = 0;
40     char ch = getchar();
41     while (ch < '0' || '9' < ch)
42         ch = getchar();
43     while ('0' <= ch && ch <= '9') {
44         x = x * 10 + ch - '0';
45         ch = getchar();
46     }
47     return x;
48 }
49
50 inline void Add_Edges(int x, int y) {
51     e[++tot] = edge(first[x], y), first[x] = tot;
52     e[++tot] = edge(first[y], x), first[y] = tot;
53 }
54
55 void dfs(int p) {
56     int i, x, y;
57     tr[p].sz = 1;
58     for (x = first[p]; x; x = e[x].next)
59         if (!tr[y = e[x].to].fa) {
60             tr[y].dep = tr[p].dep + 1;
61             tr[y].fa = p;
62             dfs(y);
63             tr[p].sz += tr[y].sz;
64             if (!tr[p].son || tr[tr[p].son].sz < tr[y].sz)
65                 tr[p].son = y;
66         }
67 }
68
69 void Dfs(int p) {
70     tr[p].w = ++cnt_tree;
71     if (!tr[p].son) return;
72     tr[tr[p].son].top = tr[p].top;
73     Dfs(tr[p].son);
74     int x, y;
75     for (x = first[p]; x; x = e[x].next)
76         if (tr[y = e[x].to].fa == p && y != tr[p].son) {
77             tr[y].top = y;
78             Dfs(y);
79         }
80 }
81
82
83 #define mid (l + r >> 1)
84 inline void refresh(int p) {
85     seg[p].mx = max(seg[seg[p].lson].mx, seg[seg[p].rson].mx);
86     seg[p].sum = seg[seg[p].lson].sum + seg[seg[p].rson].sum;
87 }
88
89 void update(int &p, int l, int r, int pos, int num) {
90     if (!p) p = ++cnt_seg;
91     if (l == r) {
92         seg[p].mx = seg[p].sum = num;
93         return;
94     }
95     if (pos <= mid) update(seg[p].lson, l, mid, pos, num);
96     else update(seg[p].rson, mid + 1, r, pos, num);
97     refresh(p);
98 }
99
100 int query_mx(int p, int l, int r, int L, int R) {
101     if (!p) return 0;
102     if (L <= l && r <= R) return seg[p].mx;
103     if (R <= mid) return query_mx(seg[p].lson, l, mid, L, R);
104     else if (mid < L) return query_mx(seg[p].rson, mid + 1, r, L, R);
105     else return max(query_mx(seg[p].lson, l, mid, L, R),
106                 query_mx(seg[p].rson, mid + 1, r, L, R));
107 }
108
109 int query_sum(int p, int l, int r, int L, int R) {
110     if (!p) return 0;
111     if (L <= l && r <= R) return seg[p].sum;
112     if (R <= mid) return query_sum(seg[p].lson, l, mid, L, R);
113     else if (mid < L) return query_sum(seg[p].rson, mid + 1, r, L, R);
114     else return query_sum(seg[p].lson, l, mid, L, R) +
115                 query_sum(seg[p].rson, mid + 1, r, L, R);
116 }
117
118
119 int work_sum(int x, int y) {
120     int C = c[x], res = 0;
121     while (tr[x].top != tr[y].top) {
122         if (tr[tr[x].top].dep < tr[tr[y].top].dep)
123             swap(x, y);
124         res += query_sum(root[C], 1, n, tr[tr[x].top].w, tr[x].w);
125         x = tr[tr[x].top].fa;
126     }
127     if (tr[x].dep < tr[y].dep)
128         swap(x, y);
129     res += query_sum(root[C], 1, n, tr[y].w, tr[x].w);
130     return res;
131 }
132
133 int work_mx(int x, int y) {
134     int C = c[x], res = 0;
135     while (tr[x].top != tr[y].top) {
136         if (tr[tr[x].top].dep < tr[tr[y].top].dep)
137             swap(x, y);
138         res = max(res, query_mx(root[C], 1, n, tr[tr[x].top].w, tr[x].w));
139         x = tr[tr[x].top].fa;
140     }
141     if (tr[x].dep < tr[y].dep)
142         swap(x, y);
143     res = max(res, query_mx(root[C], 1, n, tr[y].w, tr[x].w));
144     return res;
145 }
146
147
148 void build() {
149     int i;
150     for (i = 1; i <= n; ++i)
152     for (i = 1; i < n; ++i)
154     tr[1].fa = -1;
155     dfs(1);
156     Dfs(1);
157     for (i = 1; i <= n; ++i)
158         update(root[c[i]], 1, n, tr[i].w, w[i]);
159 }
160
161 void work() {
162     int x, y;
163     char st[10];
164     scanf("%s", st);
166     if (st[0] == 'C')
167         if (st[1] == 'C') {
168             update(root[c[x]], 1, n, tr[x].w, 0);
169             update(root[c[x] = y], 1, n, tr[x].w, w[x]);
170         }
171         else update(root[c[x]], 1, n, tr[x].w, w[x] = y);
172     else
173         if (st[1] == 'S') printf("%d\n", work_sum(x, y));
174         else printf("%d\n", work_mx(x, y));
175 }
176
177 int main() {
178     int Q;
184 }