[BZOJ 3531][SDOI 2014]旅行
动态开点线段树+树剖。
写完 编译 一遍过样例 交了 1A 这感觉还挺爽QAQ。。
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
int n, Q;
int w[maxn], c[maxn];
//-------------------------------------------------------------------//
struct Edge{
int to, next;
}edge[maxn << 1];
int h[maxn], cnt;
void add(int u, int v){
cnt ++;
edge[cnt].to = v;
edge[cnt].next = h[u];
h[u] = cnt;
}
//-------------------------------------------------------------------//
int son[maxn], top[maxn], pos[maxn], dfs_clock, size[maxn];
int fa[maxn], dep[maxn];
void dfs1(int u){
dep[u] = dep[fa[u]] + 1;
size[u] = 1;
for(int i = h[u]; i; i = edge[i].next){
int v = edge[i].to;
if(v == fa[u])continue;
fa[v] = u;
dfs1(v);
size[u] += size[v];
if(size[v] > size[son[u]])
son[u] = v;
}
}
void dfs2(int u, int tp){
pos[u] = ++ dfs_clock;
top[u] = tp;
if(son[u])dfs2(son[u], tp);
for(int i = h[u]; i; i = edge[i].next){
int v = edge[i].to;
if(v == fa[u] || v == son[u])
continue;
dfs2(v, v);
}
}
//-------------------------------------------------------------------//
#define M 10000010
int root[maxn], lc[M], rc[M], mx[M], s[M], Smz;
void pushup(int id){
s[id] = s[lc[id]] + s[rc[id]];
mx[id] = max(mx[lc[id]], mx[rc[id]]);
}
void update(int &id, int l, int r, int p, int val){
if(id == 0)id = ++ Smz;
if(l == r){s[id] = val, mx[id] = val;return;}
int mid = l + r >> 1;
if(p <= mid)update(lc[id], l, mid, p, val);
else update(rc[id], mid+1, r, p, val);
pushup(id);
}
int Asksum(int id, int l, int r, int L, int R){
if(id == 0)return 0;
if(l == L && R == r)return s[id];
int mid = l + r >> 1;
if(R <= mid)return Asksum(lc[id], l, mid, L, R);
if(L > mid) return Asksum(rc[id], mid+1, r, L, R);
return Asksum(lc[id], l, mid, L, mid) + Asksum(rc[id], mid+1, r, mid+1, R);
}
int Askmx(int id, int l, int r, int L, int R){
if(id == 0)return 0;
if(l == L && R == r)return mx[id];
int mid = l + r >> 1;
if(R <= mid)return Askmx(lc[id], l, mid, L, R);
if(L > mid) return Askmx(rc[id], mid+1, r, L, R);
return max(Askmx(lc[id], l, mid, L, mid), Askmx(rc[id], mid+1, r, mid+1, R));
}
int asksum(int u, int v){
int C = c[u], ret = 0;
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]])
swap(u, v);
ret += Asksum(root[C], 1, n, pos[top[u]], pos[u]);
u = fa[top[u]];
}
if(dep[u] > dep[v])swap(u, v);
ret += Asksum(root[C], 1, n, pos[u], pos[v]);
return ret;
}
int askmx(int u, int v){
int C = c[u], ret = 0;
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]])
swap(u, v);
ret = max(ret, Askmx(root[C], 1, n, pos[top[u]], pos[u]));
u = fa[top[u]];
}
if(dep[u] > dep[v])swap(u, v);
ret = max(ret, Askmx(root[C], 1, n, pos[u], pos[v]));
return ret;
}
int main(){
char cmd[2];
scanf("%d%d", &n, &Q);
for(int i = 1; i <= n; i ++)
scanf("%d%d", &w[i], &c[i]);
int x, y;
for(int i = 1; i < n; i ++){
scanf("%d%d", &x, &y);
add(x, y), add(y, x);
}
dfs1(1);
dfs2(1, 1);
for(int i = 1; i <= n; i ++)
update(root[c[i]], 1, n, pos[i], w[i]);
while(Q --){
scanf("%s", cmd);
scanf("%d%d", &x, &y);
switch(cmd[1]){
case 'C':
update(root[c[x]], 1, n, pos[x], 0), c[x] = y;
update(root[y], 1, n, pos[x], w[x]);
break;
case 'W':
update(root[c[x]], 1, n, pos[x], w[x] = y);
break;
case 'S':
printf("%d\n", asksum(x, y));
break;
case 'M':
printf("%d\n", askmx(x, y));
break;
}
}
return 0;
}