树剖+动态开点线段树求调(悬赏1关注)
查看原帖
树剖+动态开点线段树求调(悬赏1关注)
749959
the_night楼主2022/11/15 21:20
#include <bits/stdc++.h>
using namespace std;
#define N 100010
//定义
int n,q;
string op;
int u,v;
int w[N],c[N];
int son[N],fa[N],size[N],dep[N];
int id[N],rev[N],top[N],cnt=0,num=0;
struct list{
	int to,nxt,head;
}G[N<<1];
int tot=0;
struct node{
	int sum,mmax,l,r;
}tree[N<<4];
int root[N];
//建图 
void add(int a,int b){
	G[++tot].to=b;
	G[tot].nxt=G[a].head;
	G[a].head=tot;
}
//树剖
void dfs1(int u,int ffa){
	size[u]=1;
	dep[u]=dep[ffa]+1;
	fa[u]=ffa;
	for(int i=G[u].head;i;i=G[i].nxt){
		int v=G[i].to;
		if(v==ffa) continue;
		dfs1(v,u);
		size[u]+=size[v];
		if(size[v]>size[son[u]]) son[u]=v;
	}
}
void dfs2(int u,int t){
	top[u]=t;
	id[u]=++cnt;
	rev[cnt]=u;
	if(!son[u]) return;
	dfs2(son[u],t);
	for(int i=G[u].head;i;i=G[i].nxt){
		int v=G[i].to;
		if(v==fa[u]||v==son[u]) continue;
		dfs2(v,v);
	}
} 
//修改 
void pushup(int u){
	tree[u].sum=tree[tree[u].l].sum+tree[tree[u].r].sum;
	tree[u].mmax=max(tree[tree[u].l].mmax,tree[tree[u].r].mmax);
}
void update(int &u,int l,int r,int pos,int x){
	if(!u) u=++num;
	if(l>=pos&&r<=pos){
		tree[u].sum=x;
		tree[u].mmax=max(tree[u].mmax,x);
		return;
	}
	int mid=l+r>>1;
	if(mid>=pos) update(tree[u].l,l,mid,pos,x);
	else update(tree[u].r,mid+1,r,pos,x);
	pushup(u);
}
void update_zj(int pos,int x){
	update(root[c[x]],1,n,id[pos],w[pos]);
	update(root[c[pos]],1,n,id[pos],0); 
	c[pos]=x;
}
void update_pj(int pos,int x){
	update(root[c[pos]],1,n,id[pos],x);
	w[pos]=x;
}
//查询
int query_sum_(int u,int l,int r,int nl,int nr){
	if(l>=nl&&r<=nr) return tree[u].sum;
	int mid=l+r>>1,sum=0;
	if(mid>=nl) sum+=query_sum_(tree[u].l,l,mid,nl,nr);
	if(mid<nr) sum+=query_sum_(tree[u].r,mid+1,r,nl,nr);
	return sum;
}
int query_sum(int u,int v,int zj){
	int ans=0;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		ans+=query_sum_(root[zj],1,n,id[top[u]],id[u]);
		u=fa[top[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	ans+=query_sum_(root[zj],1,n,id[u],id[v]);
	return ans;
} 
int query_max_(int u,int l,int r,int nl,int nr){
	if(l>=nl&&r<=nr) return tree[u].mmax; 
	int mid=l+r>>1,sum=0;
	if(mid>=nl) sum=max(sum,query_max_(tree[u].l,l,mid,nl,nr));
	if(mid<nr) sum=max(sum,query_max_(tree[u].r,mid+1,r,nl,nr));
	return sum;
}
int query_max(int u,int v,int zj){
	int ans=0;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		ans=max(ans,query_max_(root[zj],1,n,id[top[u]],id[u]));
		u=fa[top[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	ans=max(ans,query_max_(root[zj],1,n,id[u],id[v]));
	return ans;
}
int main(){
	//输入 
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++){
		scanf("%d %d",&w[i],&c[i]);
	}
	for(int i=1,u,v;i<n;i++){
		scanf("%d %d",&u,&v);
		add(u,v),add(v,u);
	}
	//树剖
	dfs1(1,0),dfs2(1,1); 
	//线段树初始化
	for(int i=1;i<=n;i++){
		update(root[c[i]],1,n,id[i],w[i]);
	} 
	//问题求解
	while(q--){
		cin>>op;
		scanf("%d %d",&u,&v);
		if(op=="CC") update_zj(u,v);
		else if(op=="CW") update_pj(u,v);
		else if(op=="QS") printf("%d\n",query_sum(u,v,c[u]));
		else printf("%d\n",query_max(u,v,c[u]));
	} 
	return 0;
} 
2022/11/15 21:20
加载中...