# bzoj3531: [Sdoi2014]旅行 （树链剖分 && 动态开点线段树）

ans = max(ans, query(x, y))

query(x, y)会计算两次

  1 #include <cstdio>
2 #include <algorithm>
3 #include <vector>
4 using namespace std;
5 const int N = 100000 + 10;
6 const int M = 2000000 + 10;
7 #define isdigit(x) (x >= '0' && x <= '9')
8
9 inline void read(int &ans) {
10     ans = 0;
11     static char buf = getchar();
12     register int res = 1;
13     for (; !isdigit(buf); buf = getchar())
14         if (buf == '-') res = -1;
15     for (; isdigit(buf); buf = getchar())
16         ans = ans * 10 + buf - '0';
17     ans *= res;
18 }
19
20 int tot, n, q;
21 int sz[N], hs[N], pos[N], fa[N], top[N], w[N], c[N], dep[N];
22 vector < int > E[N];
23
24 void dfs1(int x, int d, int f) {
25     dep[x] = d; fa[x] = f;
26     hs[x] = -1; sz[x] = 1;
27     int tmp = 0;
28     for (int i = 0; i < E[x].size(); i++) {
29         int u = E[x][i];
30         if (u == f) continue;
31         dfs1(u, d + 1, x);
32         sz[x] += sz[u];
33         if (tmp < sz[u])
34             tmp = sz[u], hs[x] = u;
35     }
36 }
37
38 void dfs2(int x, int t) {
39     top[x] = t; pos[x] = ++tot;
40     if (hs[x] == -1)    return;
41     dfs2(hs[x], t);
42     for (int i = 0; i < E[x].size(); i++)
43         if (E[x][i] != fa[x] && E[x][i] != hs[x])
44             dfs2(E[x][i], E[x][i]);
45 }
46
47 int cnt;
48 int sum[M], maxn[M], ls[M], rs[M], root[N];
49
50 inline void pushUp(int o) {
51     maxn[o] = max(maxn[ls[o]], maxn[rs[o]]);
52     sum[o] = sum[ls[o]] + sum[rs[o]];
53 }
54
55 void modify(int &o, int l, int r, int p, int c) {
56     if (!o) o = ++cnt;
57     if (l == r) {
58         sum[o] = maxn[o] = c;
59         return ;
60     }
61     int mid = l + r >> 1;
62     if (p <= mid)    modify(ls[o], l, mid, p, c);
63     else    modify(rs[o], mid + 1, r, p, c);
64     pushUp(o);
65 }
66
67 int querySum(int o, int l, int r, int L, int R) {
68     if (!o) return 0;
69     if (l >= L && r <= R) return sum[o];
70     int mid = l + r >> 1, ans = 0;
71     if (L <= mid)    ans += querySum(ls[o], l, mid, L, R);
72     if (R > mid) ans += querySum(rs[o], mid + 1, r, L, R);
73     return ans;
74 }
75
76 inline int querySum(int c, int x, int y) {
77     int f1 = top[x], f2 = top[y];
78     int ans = 0;
79     while (f1 != f2) {
80         if (dep[f1] < dep[f2])
81             swap(x, y), swap(f1, f2);
82         ans += querySum(root[c], 1, n, pos[f1], pos[x]);
83         x = fa[f1]; f1 = top[x];
84     }
85     if (dep[x] > dep[y]) swap(x, y);
86     ans += querySum(root[c], 1, n, pos[x], pos[y]);
87     return ans;
88 }
89
90 int queryMax(int o, int l, int r, int L, int R) {
91     if (!o) return 0;
92     if (l >= L && r <= R) return maxn[o];
93     int mid = l + r >> 1, ans = 0;
94     if (L <= mid)    ans = max(ans, queryMax(ls[o], l, mid, L, R));
95     if (R > mid) ans = max(ans, queryMax(rs[o], mid + 1, r, L, R));
96     return ans;
97 }
98
99 inline int queryMax(int c, int x, int y) {
100     int f1 = top[x], f2 = top[y];
101     int ans = 0;
102     while (f1 != f2) {
103         if (dep[f1] < dep[f2])
104             swap(x, y), swap(f1, f2);
105         ans = max(ans, queryMax(root[c], 1, n, pos[f1], pos[x]));
106         x = fa[f1]; f1 = top[x];
107     }
108     if (dep[x] > dep[y]) swap(x, y);
109     ans = max(ans, queryMax(root[c], 1, n, pos[x], pos[y]));
110     return ans;
111 }
112
113
114 int main() {
116     for (int i = 1; i <= n; i++)
118     for (int i = 1; i < n; i++) {
119         int u, v;
121         E[u].push_back(v);
122         E[v].push_back(u);
123     }
124     dfs1(1, 0, 0); dfs2(1, 1);
125     for (int i = 1; i <= n; i++)
126         modify(root[c[i]], 1, n, pos[i], w[i]);
127     for (int i = 1; i <= q; i++) {
128         char ch[5]; scanf("%s", ch);
130         if (ch[0] == 'C') {
131             if (ch[1] == 'C') {
132                 modify(root[c[x]], 1, n, pos[x], 0);
133                 c[x] = y;
134                 modify(root[y], 1, n, pos[x], w[x]);
135             }
136             else {
137                 modify(root[c[x]], 1, n, pos[x], y);
138                 w[x] = y;
139             }
140         }
141         else {
142             if (ch[1] == 'S')
143                 printf("%d\n", querySum(c[x], x, y));
144             else    printf("%d\n", queryMax(c[x], x, y));
145         }
146     }
147     return 0;
148 }

posted @ 2018-03-19 02:29  cminus  阅读(126)  评论(0编辑  收藏  举报