Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16
HINT
思路:
这也是一个裸的树链剖分。
剖分之后,我们就用线段树维护就行。
一开始我的程序一直 T ,原因是我的数组开小了。开大一点然后就过了。
线段树维护两个值,一个是 max, 一个是 sum
#include<bits/stdc++.h>
#define lson now << 1
#define rson now << 1 | 1
using namespace std;
const int N = 3e4+100;
struct seg
{
int Max,Sum,lazy;
}tree[N<<2];
int n,m;
int Head[N],Next[N*2],To[N*2],cnt,w[N],wt[N];
int top[N],f[N],son[N],dep[N],id[N],size[N],tim;
int ans1,ans2;
void Add_edge(int u, int v){
To[++cnt] = v;
Next[cnt] = Head[u];
Head[u] = cnt;
}
void dfs1(int u, int fa){
dep[u]= dep[fa] + 1;
f[u] = fa; size[u] = 1;
for (int i = Head[u]; i; i = Next[i]){
int v = To[i];
if (v == fa) continue;
dfs1(v,u);
size[u] += size[v];
if (size[v] > size[son[u]]) son[u] = v;
}
}
void dfs2(int u, int topf){
id[u] = ++tim;
wt[tim] = w[u];
top[u] = topf;
if (!son[u]) return;
dfs2(son[u],topf);
for (int i = Head[u]; i; i = Next[i]){
int v = To[i];
if (v == f[u] || v == son[u]) continue;
dfs2(v,v);
}
}
void Build(int now, int l, int r){
if (l + 1 == r) {
tree[now].Sum = tree[now].Max = wt[l];
return;
}
int mid = (l + r) >> 1;
Build(lson,l, mid); Build(rson,mid, r);
tree[now].Sum = tree[lson].Sum + tree[rson].Sum;
tree[now].Max = max(tree[lson].Max,tree[rson].Max);
}
void Insert(int now, int l, int r, int a, int k){
if (l + 1 == r){
tree[now].Sum = k;
tree[now].Max = k;
return;
}
int mid = (l + r) >> 1;
if (a < mid) Insert(lson,l,mid,a,k);
if (a >= mid) Insert(rson,mid,r,a,k);
tree[now].Sum = tree[lson].Sum + tree[rson].Sum;
tree[now].Max = max(tree[lson].Max,tree[rson].Max);
}
void Query(int now, int l, int r, int a, int b){
if (a <= l && b >= r - 1){
ans1 += tree[now].Sum;
ans2 = max(ans2,tree[now].Max);
return;
}
int mid = (l + r) >> 1;
if (a < mid) Query(lson,l,mid,a,b);
if (b >= mid) Query(rson,mid,r,a,b);
}
void ask_query(int x, int y){
while(top[x] != top[y]){
if (dep[top[x]] < dep[top[y]]) swap(x,y);
Query(1,1,n+1,id[top[x]],id[x]);
x = f[top[x]];
}
if (dep[x] < dep[y]) swap(x,y);
Query(1,1,n+1,id[y],id[x]);
}
int main(){
int x,y;
char s[10];
scanf("%d",&n);
for (int i = 1; i < n; i++){
scanf("%d%d",&x,&y);
Add_edge(x,y); Add_edge(y,x);
}
for (int i = 1; i <= n; i++){
scanf("%d",&w[i]);
}
dfs1(1,0); dfs2(1,1);
Build(1,1,n+1);
scanf("%d",&m);
for (int i = 0; i < m; i++){
scanf("%s",s);
scanf("%d%d",&x,&y);
ans1 = 0;
ans2 = -1e5;
if (s[1] == 'H'){
Insert(1,1,n+1,id[x],y);
} else
if (s[1] == 'M') {
ask_query(x,y);
printf("%d\n",ans2);
} else{
ask_query(x,y);
printf("%d\n",ans1);
}
}
return 0;
}
/*
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
*/