【题目描述】
一棵树上有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本身
【输入格式】
输入文件的第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来一行n个整数,第i个整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
【输出格式】
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
【样例输入】
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
【样例输出】
4
1
2
2
10
6
5
6
5
16
【题意分析】
ZJOI真是暴力!!
又见暴力树剖模板,我们需要两个线段树:一个记录区间最大值,一个保留区间和。
因为是单点修改所以连lazytag都不需要啦!
最近发现我的快读老是爆炸,索性都不打快读了。
这道题给你的权值会是负数,蒟蒻写querymax函数时一开始return 0,读题好久才在题面底部发现权值可以是负数,于是改成return -INF。
就过啦!!!!
树剖程序长,做的是细心。
Code:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define MAX 100000
#define INF 1 << 29
using namespace std;
struct Front_Link_Star{
int next,to;
}edge[MAX];
int sum[MAX << 2],maxx[MAX << 2],id[MAX],top[MAX],father[MAX],depth[MAX];
int size[MAX],rk[MAX],a[MAX],head[MAX],son[MAX],cnt,dfn,n,m;
//sum[]记录区间和,maxx[]记录区间最大值
inline void Add_Edge(int u,int v){
edge[++cnt].to