Jzoj3625 旅行(travel)

非常好的树剖模板题了,直接C颗线段树上去就好了,动态开点一次写对~

#pragma GCC opitmize("O3")
#pragma G++ opitmize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 100010
#define mid (l+r>>1)
using namespace std;
struct edge{ int v,nt; } G[200010];
struct nod{ int l,r,s,m; } s[3000010];
int h[N],sz[N],top[N],son[N],f[N],d[N];
int n,m,cnt=1,tot=0,clk=0,w[N],l[N],c[N],rt[N];
inline void gmax(int& x,int y){ x<y?x=y:0; }
inline void ps(nod& x){
	x.s=s[x.l].s+s[x.r].s;
	x.m=max(s[x.l].m,s[x.r].m);
}
inline void adj(int x,int y){ 
	G[++cnt]=(edge){y,h[x]}; h[x]=cnt;
	G[++cnt]=(edge){x,h[y]}; h[y]=cnt;
}
void dfs(int x,int p){
	d[x]=d[p]+1; sz[x]=1; f[x]=p;
	for(int v,i=h[x];i;i=G[i].nt)
		if(!d[v=G[i].v]){
			dfs(v,x); sz[x]+=sz[v];
			if(sz[v]>sz[son[x]]) son[x]=v;
		}
}
void dgs(int x,int p){
	top[x]=p; l[x]=++clk;
	if(son[x]) dgs(son[x],p);
	for(int v,i=h[x];i;i=G[i].nt)
		if(!l[v=G[i].v]) dgs(v,v);
}
void insert(int l,int r,int& x,int p,int k){
	if(!x) x=++tot;
	if(l==r) { s[x].s=s[x].m=k; return; }
	if(p<=mid) insert(l,mid,s[x].l,p,k);
		else insert(mid+1,r,s[x].r,p,k);
	ps(s[x]);
}
void remove(int l,int r,int& x,int p){
	if(l==r){ x=0; return; }
	if(p<=mid) remove(l,mid,s[x].l,p);
		else remove(mid+1,r,s[x].r,p);
	if(s[x].l || s[x].r) ps(s[x]); else x=0;
}
void modify(int l,int r,int x,int p,int k){
	if(l==r){ s[x].s=s[x].m=k; return; }
	if(p<=mid) modify(l,mid,s[x].l,p,k);
		else modify(mid+1,r,s[x].r,p,k);
	ps(s[x]);
}
int queryS(int l,int r,int x,int L,int R){
	if(!x) return 0;
	if(L<=l && r<=R) return s[x].s;
	int ans=0;
	if(L<=mid) ans+=queryS(l,mid,s[x].l,L,R);
	if(mid<R) ans+=queryS(mid+1,r,s[x].r,L,R);
	return ans;
}
int gSum(int x,int y){
	int ans=0,C=c[x];
	for(;top[x]!=top[y];y=f[top[y]]){
		if(d[top[x]]>d[top[y]]) swap(x,y);
		ans+=queryS(1,n,rt[C],l[top[y]],l[y]);
	}
	if(d[x]>d[y]) swap(x,y);
	return ans+queryS(1,n,rt[C],l[x],l[y]);
}
int queryM(int l,int r,int x,int L,int R){
	if(!x) return 0;
	if(L<=l && r<=R) return s[x].m;
	int ans=0;
	if(L<=mid) gmax(ans,queryM(l,mid,s[x].l,L,R));
	if(mid<R) gmax(ans,queryM(mid+1,r,s[x].r,L,R));
	return ans;
}
int gMax(int x,int y){
	int ans=0,C=c[x];
	for(;top[x]!=top[y];y=f[top[y]]){
		if(d[top[x]]>d[top[y]]) swap(x,y);
		gmax(ans,queryM(1,n,rt[C],l[top[y]],l[y]));
	}
	if(d[x]>d[y]) swap(x,y);
	return max(ans,queryM(1,n,rt[C],l[x],l[y]));
}
int main(){
	freopen("travel.in","r",stdin);
	freopen("travel.out","w",stdout); 
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i) scanf("%d%d",w+i,c+i);
	for(int x,y,i=1;i<n;++i) scanf("%d%d",&x,&y),adj(x,y); 
	dfs(1,0); dgs(1,1); char o[3];
	for(int i=1;i<=n;++i) insert(1,n,rt[c[i]],l[i],w[i]);
	for(int x,y;m--;){
		scanf("%s%d%d",o,&x,&y);
		if(*o=='C'){
			if(o[1]=='C'){
				remove(1,n,rt[c[x]],l[x]);
				insert(1,n,rt[y],l[x],w[x]);
				c[x]=y;
			} else {
				modify(1,n,rt[c[x]],l[x],y);
				w[x]=y;
			}
		} else {
			if(o[1]=='S') printf("%d\n",gSum(x,y));
					else printf("%d\n",gMax(x,y));
		}
	}
}

posted @ 2017-12-13 20:29  扩展的灰(Extended_Ash)  阅读(111)  评论(0编辑  收藏  举报