题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3531
解题心得:
- 关于树剖的部分很容易想到,树上的简单路径维护值的问题肯定是要树链剖分了,但是线段树怎么维护就很讲究了,因为有不同的阵营,如果维护每个阵营就需要建立n颗线段树,如果静态建立线段树肯定会MLE,这里就只需要动态建立线段树就行了。
- 在树链剖分的时候,在同一条重链上重链的哪一个端点设定的标号更大一定要搞清楚,不然线段树对应的区间就要写反,写BUG了还过了一个88MB的数据,找了半天没发现,结果还是对拍来得快。之前想到88MB的数据都过了,就没去想对拍但是眼睛都看瞎了都没发现BUG。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 2e6+1000;
struct Node {
ll belong, va, num, fa, gr_fa, deep, size;
}p[maxn];
struct Node2 {
ll ls, rs, sum, max;
}node[maxn];
vector <ll> ve[maxn];
ll n, m, rt[maxn], Index, tot;
void init() {
scanf("%lld%lld",&n, &m);
for(ll i=1;i<=n;i++) {
ll a, b; scanf("%lld%lld", &a, &b);
p[i].va = a;
p[i].belong = b;
}
for(ll i=1;i<n;i++) {
ll a, b; scanf("%lld%lld",&a, &b);
ve[a].push_back(b);
ve[b].push_back(a);
}
}
ll get_deep_size(ll pre, ll now, ll dep) {
p[now].fa = pre;
p[now].deep = dep;
p[now].size = 1;
for(ll i=0;i<ve[now].size();i++) {
ll v = ve[now][i];
if(v == pre) continue;
p[now].size += get_deep_size(now, v, dep+1);
}
return p[now].size;
}
void dfs(ll pre, ll now, ll w) {
if(w == 0) p[now].gr_fa = now;
else p[now].gr_fa = p[pre].gr_fa;
p[now].num = ++Index;
ll Max = 0, pos = -1;
for(ll i=0;i<ve[now].size();i++) {
ll v = ve[now][i];
if(v == pre) continue;
if(p[v].size > Max) {
Max = p[v].size;
pos = v;
}
}
if(pos == -1) return;
dfs(now, pos, 1);
for(ll i=0;i<ve[now].size();i++) {
ll v = ve[now][i];
if(v == pre || v == pos) continue;
dfs(now, v, 0);
}
}
void update(ll root) {
node[root].sum = node[node[root].ls].sum + node[node[root].rs].sum;
node[root].max = max(node[node[root].ls].max, node[node[root].rs].max);
}
void insert(ll root, ll l, ll r, ll pos, ll va) {
if(l == r) {
node[root].sum = va;
node[root].max = va;
return ;
}
ll mid = l + r >> 1;
if(pos <= mid) {
if(node[root].ls == 0) node[root].ls = ++tot;
insert(node[root].ls, l, mid, pos, va);
} else {
if(node[root].rs == 0) node[root].rs = ++tot;
insert(node[root].rs, mid+1, r, pos, va);
}
update(root);
}
void build_tree() {
for(ll i=1;i<=n;i++) {
ll pos = p[i].num;
if(rt[p[i].belong] == 0) {
rt[p[i].belong] = ++tot;
}
insert(rt[p[i].belong], 1, Index, pos, p[i].va);
}
}
ll query_sum(ll root, ll l, ll r, ll ql, ll qr) {
if(root == 0) return 0;
if(l == ql && r == qr) return node[root].sum;
ll mid = l + r >>1;
if(qr <= mid) return query_sum(node[root].ls, l, mid, ql, qr);
else if(ql > mid) return query_sum(node[root].rs, mid+1, r, ql, qr);
else {
return query_sum(node[root].ls, l, mid, ql, mid) +
query_sum(node[root].rs, mid+1, r, mid+1, qr);
}
}
ll query_max(ll root, ll l, ll r, ll ql, ll qr) {
if(root == 0) return 0;
if(l == ql && r == qr) return node[root].max;
ll mid = l + r >> 1;
if(qr <= mid) return query_max(node[root].ls, l, mid, ql, qr);
else if(ql > mid) return query_max(node[root].rs, mid+1, r, ql, qr);
else return max(query_max(node[root].ls, l, mid, ql, mid),
query_max(node[root].rs, mid+1, r, mid+1, qr));
}
ll query(ll x, ll y, ll belong, ll w) {
ll sum = 0, Max = 0;
while(p[x].gr_fa != p[y].gr_fa) {
if(p[p[x].gr_fa].deep < p[p[y].gr_fa].deep) swap(x, y);
ll r = p[x].num;
ll l = p[p[x].gr_fa].num;
if(w == 0) {
sum += query_sum(rt[belong], 1, Index, l, r);
} else {
Max = max(Max, query_max(rt[belong], 1, Index, l, r));
}
x = p[p[x].gr_fa].fa;
}
if(p[x].num > p[y].num) swap(x, y);
if(w == 0) sum += query_sum(rt[belong], 1, Index, p[x].num, p[y].num);
else Max = max(Max, query_max(rt[belong], 1, Index, p[x].num, p[y].num));
if(w == 0) return sum;
else return Max;
}
vector <int> path;
bool dfs2(int pre, int now, int aim) {
if(now == aim) {
path.push_back(now);
return true;
}
for(int i=0;i<ve[now].size();i++) {
int v = ve[now][i];
if(v == pre) continue;
if(dfs2(now, v, aim)) {
path.push_back(now);
return true;
}
}
return false;
}
int main() {
// freopen("1.in.txt", "r", stdin);
init();
get_deep_size(1, 1, 1);
dfs(1, 1, 0);
build_tree();
while(m--) {
char s[5];
scanf("%s", s);
if(strcmp(s, "CC") == 0) {
ll a, b; scanf("%lld%lld", &a, &b);
insert(rt[p[a].belong], 1, Index, p[a].num, 0);
p[a].belong = b;
if(rt[p[a].belong] == 0) rt[p[a].belong] = ++tot;
insert(rt[p[a].belong], 1, Index, p[a].num, p[a].va);
} else if(strcmp(s, "CW") == 0) {
ll a, b; scanf("%lld%lld",&a, &b);
p[a].va = b;
insert(rt[p[a].belong], 1, Index, p[a].num, b);
} else if(strcmp(s, "QS") == 0) {
ll a, b;
scanf("%lld%lld", &a, &b);
printf("%lld\n", query(a, b, p[b].belong, 0));
} else {
ll a, b; scanf("%lld%lld", &a, &b);
printf("%lld\n", query(a, b, p[b].belong, 1));
}
}
return 0;
}