题目链接:BZOJ3551
题目大意
维护一棵树,树上每个点两个权值
C
和
1.
CC i X
,修改点
i
的权值
2.
3.
4.
QM i j
(保证
Ci=Cj
),求
maxx∈ACx=CiWx
,其中A为从i到j的路径上点的集合(包括
i
和
题目分析
1. 首先有个显然的做法:维护
C
棵线段树,
2. 对于树上每个点,只会存在于一颗线段树上,于是我们可以动态开点回收;
3. 当一个点从一颗线段树转移到另一颗线段树时,从原线段树上删掉它,并在新线段树上添加;
4. 对于线段树上的某个点,如果它对应的区间里面一个点都没有,那么这个点也可以删掉,这样的话所有点的数量就是
NlogN
啦。
上代码
#include <stack>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
const int M = 2e6 + 10;
int n, q;
inline int read() {
char ch;
int ans = 0, neg = 1;
while (!isdigit(ch = getchar()))
if (ch == '-') neg = -1;
while (isdigit(ch))
ans = ans * 10 + ch - '0', ch = getchar();
return ans * neg;
}
int rel[N], val[N];
vector <int> edge[N];
namespace HLD {
int fa[N], son[N], dep[N], size[N];
int top[N], plc[N], replc[N], cntSeg;
void dfs1(int a, int par) {
dep[a] = dep[fa[a] = par] + (size[a] = 1);
for (int i = 0; i < edge[a].size(); i++) {
int cur = edge[a][i];
if (cur == par) continue;
dfs1(cur, a), size[a] += size[cur];
if (size[cur] > size[son[a]]) son[a] = cur;
}
}
void dfs2(int a, int up) {
top[a] = up, replc[plc[a] = ++cntSeg] = a;
if (son[a]) dfs2(son[a], up);
for (int i = 0; i < edge[a].size(); i++) {
int cur = edge[a][i];
if (cur == fa[a] || cur == son[a]) continue;
dfs2(cur, cur);
}
}
int cnt = 1e5;
stack <int> bin;
int lc[M], rc[M], lp[M], rp[M];
int tot[M], maxn[M];
#define isRoot(a) (lp[a] == 1 && rp[a] == n)
inline int getNew(int l, int r) {
int tmp = 0;
if (bin.empty()) tmp = ++cnt;
else tmp = bin.top(), bin.pop();
tot[tmp] = maxn[tmp] = 0;
lc[tmp] = rc[tmp] = 0, lp[tmp] = l, rp[tmp] = r;
return tmp;
}
void build() {
for (int i = 1; i <= cnt; i++)
lp[i] = 1, rp[i] = n;
}
inline void pushUp(int a) {
tot[a] = tot[lc[a]] + tot[rc[a]];
maxn[a] = max(maxn[lc[a]], maxn[rc[a]]);
}
void add(int a, int p) {
if (lp[a] == rp[a])
return tot[a] = maxn[a] = val[replc[p]], void(0);
int mid = (lp[a] + rp[a]) >> 1;
if (p <= mid) {
if (!lc[a]) lc[a] = getNew(lp[a], mid);
add(lc[a], p);
} else {
if (!rc[a]) rc[a] = getNew(mid + 1, rp[a]);
add(rc[a], p);
} pushUp(a);
}
bool delett(int a, int p) {
if (lp[a] == rp[a])
return bin.push(a), true;
int mid = (lp[a] + rp[a]) >> 1;
if (p <= mid && delett(lc[a], p) && (lc[a] = 0, !rc[a]) && !isRoot(a))
return bin.push(a), true;
else if (p > mid && delett(rc[a], p) && (rc[a] = 0, !lc[a]) && !isRoot(a))
return bin.push(a), true;
return pushUp(a), false;
}
void modify(int a, int p) {
if (lp[a] == p && rp[a] == p)
return tot[a] = maxn[a] = val[replc[p]], void(0);
int mid = (lp[a] + rp[a]) >> 1;
if (p <= mid) modify(lc[a], p);
else modify(rc[a], p);
pushUp(a);
}
int queryMax(int a, int l, int r) {
if (a == 0) return 0;
if (lp[a] == l && rp[a] == r)
return maxn[a];
int mid = (lp[a] + rp[a]) >> 1;
if (r <= mid) return queryMax(lc[a], l, r);
else if (l > mid) return queryMax(rc[a], l, r);
else return max(queryMax(lc[a], l, mid), queryMax(rc[a], mid + 1, r));
}
int queryTot(int a, int l, int r) {
if (a == 0) return 0;
if (lp[a] == l && rp[a] == r)
return tot[a];
int mid = (lp[a] + rp[a]) >> 1;
if (r <= mid) return queryTot(lc[a], l, r);
else if (l > mid) return queryTot(rc[a], l, r);
else return queryTot(lc[a], l, mid) + queryTot(rc[a], mid + 1, r);
}
int decomMax(int s, int a, int b) {
int ans = 0;
while (top[a] != top[b]) {
if (dep[top[a]] < dep[top[b]]) swap(a, b);
ans = max(ans, queryMax(s, plc[top[a]], plc[a]));
a = fa[top[a]];
}
if (dep[a] < dep[b]) swap(a, b);
ans = max(ans, queryMax(s, plc[b], plc[a]));
return ans;
}
int decomTot(int s, int a, int b) {
int ans = 0;
while (top[a] != top[b]) {
if (dep[top[a]] < dep[top[b]]) swap(a, b);
ans += queryTot(s, plc[top[a]], plc[a]);
a = fa[top[a]];
}
if (dep[a] < dep[b]) swap(a, b);
ans += queryTot(s, plc[b], plc[a]);
return ans;
}
}
void init() {
n = read(), q = read();
for (int i = 1; i <= n; i++)
val[i] = read(), rel[i] = read();
for (int i = 1; i < n; i++) {
int a = read(), b = read();
edge[a].push_back(b), edge[b].push_back(a);
}
HLD::dfs1(1, 0), HLD::dfs2(1, 1), HLD::build();
for (int i = 1; i <= n; i++)
HLD::add(rel[i], HLD::plc[i]);
}
void figure() {
char ss[5]; int a, b;
for (int i = 1; i <= q; i++) {
scanf("%s", ss), a = read(), b = read();
if (ss[1] == 'C') {
HLD::delett(rel[a], HLD::plc[a]);
HLD::add(rel[a] = b, HLD::plc[a]);
} else if (ss[1] == 'W') {
val[a] = b;
HLD::modify(rel[a], HLD::plc[a]);
} else if (ss[1] == 'S')
printf("%d\n", HLD::decomTot(rel[a], a, b));
else if (ss[1] == 'M')
printf("%d\n", HLD::decomMax(rel[a], a, b));
}
}
int main() {
init();
figure();
return 0;
}
以上