Bootstrap

「一本通 4.5 例 1」树的统计 树链剖分

#include<bits/stdc++.h>
using namespace std;
#define Mid ((l+r)>>1)  
#define lson rt<<1,l,Mid  
#define rson rt<<1|1,Mid+1,r 
const int maxn = 3e4+10, inf = 3e4 + 10;
int To[maxn<<1], Next[maxn<<1], Begin[maxn], tot;
int n, q, Sum[maxn<<2], Max[maxn<<2], a[maxn];
int fa[maxn], dis[maxn], size[maxn], son[maxn];
int id[maxn], Rank[maxn], top[maxn], cnt;
void add(int x,int y){To[++tot] = y; Next[tot] = Begin[x];	Begin[x] = tot;}
void dfs1(int rt,int f){	
	size[rt] = 1;		
	dis[rt] = dis[f]+1;
	for(int i = Begin[rt] ; i ; i = Next[i]){
		int u = To[i];		
		if(u != f){			
			fa[u] = rt;	
			dfs1(u, rt);
			size[rt] += size[u];
			if(size[u] > size[son[rt]])son[rt] = u;			
		}
	}
}
void dfs2(int rt,int tp){
	top[rt] = tp;
	id[++cnt] = rt;	Rank[rt] = cnt;
	if(son[rt])dfs2(son[rt], tp);
	for(int i = Begin[rt]; i; i = Next[i]){
		int u = To[i];
		if(u != son[rt] && u != fa[rt])dfs2(u,u);
	}
}
void update(int rt,int l,int r,int pos,int num){  
    if(l == r && r == pos){
        Sum[rt] = num;
		Max[rt] = num;  
    }else{  
        if( pos <= Mid)  
            update(lson,pos,num);  
        if( pos > Mid)  
            update(rson,pos,num);  
        Sum[rt] = Sum[rt<<1] + Sum[rt<<1|1];
        Max[rt] = max(Max[rt<<1], Max[rt<<1|1]);
    }  
}
int query(int rt, int l, int r, int L, int R, int op){  
    if(L <= l && r <= R)return op == 1 ? Sum[rt] : Max[rt];  
    if(op == 1){      
		int tmp = 0;   
        if(L <= Mid)tmp += query(lson, L, R, op);
        if(R > Mid)tmp += query(rson, L, R, op);
        return tmp; 
    }else{
		int tmp = -inf;   
        if(L <= Mid)tmp = max(tmp, query(lson, L, R, op));
        if(R > Mid)tmp = max(tmp, query(rson, L, R, op));
        return tmp; 	
	}
}
int main(){
	cin >> n;
	for(int i = 1; i < n; i++){
		int x, y;	scanf("%d%d", &x, &y);
		add(x, y);	add(y, x);
	}
	
	dfs1(1, 0);	dfs2(1, 1);
	for(int i = 1; i <= n; i++){
		scanf("%d", &a[i]);
		update(1, 1, n, Rank[i], a[i]);	
	}
	cin >> q;
	for(int i = 1; i <= q; i++){
		int x, y;	string op;
		cin >> op >> x >> y;
		if(op == "CHANGE"){
			scanf("%d%d", &x, &y);
			update(1, 1, n, Rank[x], -a[x]);
			update(1, 1, n, Rank[x], y);
			a[x] = y;		
		}else if(op == "QSUM"){
			int ans = 0;
			while(top[x] != top[y]){
				if(dis[top[x]] < dis[top[y]])swap(x, y);
				ans += query(1, 1, n, Rank[top[x]], Rank[x], 1);
				x = fa[top[x]];								
			}
			if(dis[x] < dis[y])swap(x, y);
			ans += query(1, 1, n, Rank[y], Rank[x], 1);			
			printf("%d\n",ans);
		}else if(op == "QMAX"){
			int ans = -inf;
			while(top[x] != top[y]){
				if(dis[top[x]] < dis[top[y]])swap(x, y);
				ans = max(ans, query(1, 1, n, Rank[top[x]], Rank[x], 0));
				x = fa[top[x]];								
			}
			if(dis[x] < dis[y])swap(x, y);
			ans = max(ans, query(1, 1, n, Rank[y], Rank[x], 0));			
			printf("%d\n",ans);
		}
	}
	return 0;
}
;