Description
一棵樹上有n個節點,編號分別爲1到n,每個節點都有一個權值w。我們將以下面的形式來要求你對這棵樹完成 一些操作:
I. CHANGE u t : 把結點u的權值改爲t
II. QMAX u v: 詢問從點u到點v的路徑上的節點的最大權值
III. 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
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int SZ = 400010;
struct SGT
{
int l, r;
LL sum, maxx;
}sgt[SZ];
struct Tree
{
int f, t;
}tree[SZ];
int size[SZ], first[SZ], nxt[SZ], fa[SZ], deep[SZ], son[SZ], num[SZ], tot;
void Build(int f, int t)
{
tree[++tot] = (Tree){f, t};
nxt[tot] = first[f];
first[f] = tot;
}
void DFS_1(int u, int f)
{
fa[u] = f;
deep[u] = deep[f] + 1;
size[u] = 1;
for(int i = first[u]; i; i = nxt[i])
{
int v = tree[i].t;
if(v == f) continue;
DFS_1(v, u);
size[u] += size[v];
if(!son[u] || size[v] > size[son[u]]) son[u] = v;
}
}
int top[SZ], inseg[SZ], intree[SZ], topa;
void DFS_2(int u, int topu)
{
top[u] = topu;
inseg[u] = ++ topa;
intree[topa] = u;
if(!son[u]) return ;
DFS_2(son[u], topu);
for(int i = first[u]; i; i = nxt[i])
{
int v = tree[i].t;
if(v == son[u] || v == fa[u]) continue;
DFS_2(v, v);
}
}
void update(int now)
{
sgt[now].sum = sgt[now << 1].sum + sgt[now << 1 | 1].sum;
sgt[now].maxx = max(sgt[now << 1].maxx, sgt[now << 1 | 1].maxx);
}
void Build_Tree(int now, int l, int r)
{
sgt[now].l = l; sgt[now].r = r;
if(l == r)
{
sgt[now].sum = sgt[now].maxx = num[intree[l]];
return ;
}
int mid = (l + r) >> 1;
Build_Tree(now << 1, l, mid);
Build_Tree(now << 1 | 1, mid + 1, r);
update(now);
}
void Change(int now, int point, int value)
{
if(sgt[now].l == sgt[now].r)
{
sgt[now].sum = value;
sgt[now].maxx = value;
return ;
}
int mid = (sgt[now].l + sgt[now].r) >> 1;
if(point <= mid) Change(now << 1, point, value);
if(point > mid) Change(now << 1 | 1, point, value);
update(now);
}
LL Ask_Max(int now, int l, int r)
{
if(l <= sgt[now].l && sgt[now].r <= r)
return sgt[now].maxx;
int mid = (sgt[now].l + sgt[now].r) >> 1;
LL maxn = -SZ;
if(l <= mid) maxn = max(maxn, Ask_Max(now << 1, l, r));
if(r > mid) maxn = max(maxn, Ask_Max(now << 1 | 1, l, r));
return maxn;
}
LL Ask_Sum(int now, int l, int r)
{
if(l <= sgt[now].l && sgt[now].r <= r)
return sgt[now].sum;
int mid = (sgt[now].l + sgt[now].r) >> 1;
LL sum = 0;
if(l <= mid) sum += Ask_Sum(now << 1, l, r);
if(r > mid) sum += Ask_Sum(now << 1 | 1, l, r);
return sum;
}
LL Max(int l, int r)
{
int fal = top[l], far = top[r];
LL maxn = -SZ;
while(fal != far)
{
if(deep[fal] < deep[far])
{
swap(l, r); swap(fal, far);
}
maxn = max(maxn, Ask_Max(1, inseg[fal], inseg[l]));
l = fa[fal]; fal = top[l];
}
if(deep[l] > deep[r]) swap(l, r);
maxn = max(maxn, Ask_Max(1, inseg[l], inseg[r]));
return maxn;
}
LL Sum(int l, int r)
{
int fal = top[l], far = top[r];
LL ans = 0;
while(fal != far)
{
if(deep[fal] < deep[far]) swap(l, r), swap(fal, far);
ans += Ask_Sum(1, inseg[fal], inseg[l]);
l = fa[fal]; fal = top[l];
}
if(deep[l] > deep[r]) swap(l, r);
ans += Ask_Sum(1, inseg[l], inseg[r]);
return ans;
}
int main()
{
int n;
scanf("%d", &n);
int f, t;
for(int i = 1; i < n; i++)
{
scanf("%d%d", &f, &t);
Build(f, t);
Build(t, f);
}
for(int i = 1; i <= n; i++)
scanf("%d", &num[i]);
DFS_1(1, 0);
DFS_2(1, 1);
Build_Tree(1, 1, n);
int q;
char op[10];
int a, b;
scanf("%d", &q);
for(int i = 1; i <= q; i++)
{
scanf("%s", op);
scanf("%d%d", &a, &b);
if(op[0] == 'Q' && op[1] == 'M')
printf("%lld\n", Max(a, b));
else if (op[0] == 'Q' && op[1] == 'S')
printf("%lld\n", Sum(a, b));
else
Change(1, inseg[a], b), num[a] = b;
}
return 0;
}