树链剖分模板求改错qaq
  • 板块学术版
  • 楼主南瓜桐
  • 当前回复12
  • 已保存回复13
  • 发布时间2024/5/23 22:17
  • 上次更新2024/5/24 13:09:38
查看原帖
树链剖分模板求改错qaq
439327
南瓜桐楼主2024/5/23 22:17

P2590 [ZJOI2008] 树的统计
Orz

#include <bits/stdc++.h>
using namespace std;
int n, q;
const int maxn = 3e4 + 1;
const int inf = 3e4; 
struct edge{
	int fr,to,nxt;
}e[maxn*2] = {};
int head[maxn] = {}, cnt_edge = 0;
int w[maxn] = {};
int dfn[maxn] = {}, rnk[maxn] = {}, son[maxn] = {}, siz[maxn] = {}, dep[maxn] = {}, fa[maxn] = {}, top[maxn] = {};

struct segTree{
	int sum[maxn*4]	, maxx[maxn*4];
	segTree(){
		memset(sum,0,sizeof(sum));
		memset(maxx,0,sizeof(maxx));
	}
	
	void buildTree(int s, int t, int node){
		int left = 2*node, right = 2*node + 1, mid = (s+t)/2;
		if(s == t){
			sum[node] = maxx[node] = w[rnk[t]];
		}
		buildTree(s,mid,left);
		buildTree(mid+1,t,right);
		sum[node] = sum[left] + sum[right];
		maxx[node] = max(maxx[left],maxx[right]);
	}
	
	int getsum(int l, int r, int s, int t, int node){
		int left = 2*node, right = 2*node + 1, mid = (s+t)/2;
		if(s > r || t < l) return 0;
		if(l <= s && t <= r) return sum[node];
		return (getsum(l,r,s,mid,left) + getsum(l,r,mid+1,t,right));
	}
	
	int getmax(int l, int r, int s, int t, int node){
		int left = 2*node, right = 2*node + 1, mid = (s+t)/2;
		if(s > r || t < l) return -inf;
		if(l <= s && t <= r) return maxx[node];
		return (getsum(l,r,s,mid,left) + getsum(l,r,mid+1,t,right));
	}
	
	void update(int x, int k, int s, int t, int node){
		int left = 2*node, right = 2*node + 1, mid = (s+t)/2;
		if(s == t){
			sum[t] = maxx[t] = k;
			return ;
		}
		if(x <= mid) update(x,k,s,mid,left);
		if(x > mid) update(x,k,mid+1,t,right);
		sum[node] = sum[left] + sum[right];
		maxx[node] = max(maxx[left],maxx[right]);
	}
	
}st;
void add_edge(int u, int v){
	e[++cnt_edge] = (edge){u,v,head[u]};
	head[u] = cnt_edge;
}
void dfs1(int u){
	son[u] = -1;
	siz[u] = 1;
	for(int i = head[u]; i != -1; i = e[i].nxt){
		int v = e[i].to;
		if(!dep[v]){
			dep[v] = dep[u] + 1;
			fa[v] = u;
			dfs1(v);
			siz[u] += v;
			if(son[u] == -1 || siz[son[u]] < siz[v] ) son[u] = v;
		}
	}
}
int cnt_dfn = 0;
void dfs2(int u, int t){
	dfn[u] = ++cnt_dfn;
	rnk[cnt_dfn] = u;
	top[u] = u;
	dfs2(son[u], t);	if(son[u] == -1) return;

	for(int i = head[u]; i != -1; i = e[i].nxt){
		int v = e[i].to;
		if(v != fa[u] && v != son[u]) dfs2(v,v);
	}
}
int queryMax(int u, int v){
	int ans = -inf;
	while(top[u] != top[v]){
		if(dep[top[v]] > dep[top[u]]) swap(u,v);
		ans = max(ans, st.getmax(dfn[u],dfn[top[u]],1,n,1));
		u = fa[top[u]];
	}
	if(dfn[u] > dfn[v]) swap(u,v);
	ans = max(ans, st.getmax(dfn[u],dfn[v],1,n,1));
	return ans;
}
int querySum(int u, int v){
	int ans = 0;
	while(top[u] != top[v]){
		if(dep[top[v]] > dep[top[u]]) swap(u,v);
		ans += st.getsum(dfn[u],dfn[top[u]],1,n,1);
		u = fa[top[u]];
	}
	if(dfn[u] > dfn[v]) swap(u,v);
	ans += st.getsum(dfn[u],dfn[v],1,n,1);
	return ans;
}
int main(){
	cin>>n;
	memset(head, -1, sizeof(head));
	for(int i = 1; i <= n-1; ++i) {
		int u,v;
		scanf("%d%d",&u,&v);
		add_edge(u , v); add_edge(v, u);
	}
	for(int i = 1; i <= n; ++i) cin>>w[i];
	
	dep[1] = 1;
	dfs1(1);
	dfs2(1,1);
	st.buildTree(1,n,1);
	do{
		string s; 
		int u, v;
		cin>>s>>u>>v;
		if(s == "CHANGE"){
			st.update(dfn[u],v,1,n,1);
		}
		if(s == "QMAX"){
			printf("%d\n",queryMax(u,v));
		}
		if(s == "QSUM"){
			printf("%d\n",querySum(u,v));
		}
	}while(--q);
	return 0;
}
2024/5/23 22:17
加载中...