ZJOI2008 树的统计

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

树剖模板题。

//脱壳壳,结构体+inline+vector会re 
#include
#define N 50001
using namespace std;
inline int get(){register int re=0,f=1;register char c;while(c=getchar(),(c>='0'&&c<='9')^1)f=c^'-';while(re=(re<<1)+(re<<3)+(c^48),c=getchar(),(c>='0'&&c<='9'));return f?re:-re;}
#define FOR(i,L,R) for(register int i=(L);i<=(R);++i)
#define REP(i,R,L) for(register int i=(R);i>=(L);--i)
int n,m,cnt;
struct Graph{//构图finish 
	vectorG[N];
	int p[N],fa[N];
	int siz[N],son[N],dep[N];
	int top[N];
	#define to G[x][i]
	inline void dfs2(int x,int sp){
		top[x]=sp;
		p[x]=++cnt;
		if(son[x])dfs2(son[x],sp);
		int sz=G[x].size()-1;
		FOR(i,0,sz)if(to^fa[x]&&to^son[x])dfs2(to,to);
	}
	inline void dfs1(int x,int Fa,int depth){
		int sz=G[x].size()-1;
		FOR(i,0,sz)if(to^Fa){
			dfs1(to,fa[to]=x,dep[to]=depth+1);
			siz[x]+=siz[to];
			if(siz[son[x]]>1]+=sum[i];
		REP(i,M+x,1)k[i>>1]=max(k[i>>1],k[i]);
	}
	inline void Edit(int x,int v){
		k[M+x]=sum[M+x]=v;
		x+=M;
		while(x)k[x>>1]=max(k[x],k[x^1]),sum[x>>=1]=sum[x<<1]+sum[x<<1|1];
	}
	inline int Sum(int L,int r){
		int ans=0;
		for(register int s=M+L-1,t=M+r+1;s^t^1;s>>=1,t>>=1){
			if(~s&1)ans+=sum[s^1];
			if(t&1)ans+=sum[t^1];
		}return ans;
	}
	inline int Max(int L,int r){
		int ans=-1e8;
		for(register int s=M+L-1,t=M+r+1;s^t^1;s>>=1,t>>=1){
			if(~s&1)ans=max(ans,k[s^1]);
			if(t&1)ans=max(ans,k[t^1]);
		}return ans;
	}
}t;
inline void GETSUM(int x,int y){
	int t1=top(x),t2=top(y);
	int ans=0;
	while(t1!=t2){
		if(dep(t1)dep(y))swap(x,y);
	cout<dep(y))swap(x,y);
	cout<

 

你可能感兴趣的:(数据结构,树剖)