bzoj 3531 旅行 Posted on 2019-09-02 | Views: 动态开点线段树. 先上个树链剖分,转化成序列上的问题. 只有 $10^5$ 种宗教,可以给每种宗教开一棵动态开点线段树维护信息. 修改宗教只有单点修改,比较容易处理,随便写一写就可以了. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169#include<bits/stdc++.h>using namespace std;typedef long long ll;inline int read(){ int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int MAXN=1e5+10;ll ans;int cnt=0;struct Segtree{ struct node { int ls,rs; int mx; ll sum; node(){mx=sum=0;} }Tree[MAXN*20];#define root Tree[o]#define lson Tree[root.ls]#define rson Tree[root.rs] void pushup(int o) { root.mx=max(lson.mx,rson.mx); root.sum=lson.sum+rson.sum; } void upd(int &o,int l,int r,int pos,int c) { if(!o) o=++cnt; if(l==r) return (void)(root.sum=root.mx=c); int mid=(l+r)>>1; if(pos<=mid) upd(root.ls,l,mid,pos,c); else upd(root.rs,mid+1,r,pos,c); pushup(o); } void query(int o,int l,int r,int L,int R,int op) { if(!o) return; if(L<=l && r<=R) { if(!op) ans=max(ans,1LL*root.mx); else ans+=root.sum; return; } int mid=(l+r)>>1; if(L<=mid) query(root.ls,l,mid,L,R,op); if(R>mid) query(root.rs,mid+1,r,L,R,op); }}T;int rt[MAXN];int ecnt=0,head[MAXN],to[MAXN<<1],nx[MAXN<<1];void addedge(int u,int v){ ++ecnt; to[ecnt]=v; nx[ecnt]=head[u]; head[u]=ecnt;}int n,m,k;int idx=0,siz[MAXN],mxson[MAXN],dep[MAXN],top[MAXN],fa[MAXN],dfn[MAXN];int w[MAXN],c[MAXN];void dfs1(int u,int f){ fa[u]=f; siz[u]=1; for(int i=head[u];i;i=nx[i]) { int v=to[i]; if(v==f) continue; dep[v]=dep[u]+1; dfs1(v,u); siz[u]+=siz[v]; if(siz[v]>siz[mxson[u]]) mxson[u]=v; }}void dfs2(int u,int tp){ top[u]=tp; dfn[u]=++idx; T.upd(rt[c[u]],1,n,dfn[u],w[u]); if(mxson[u]) dfs2(mxson[u],tp); for(int i=head[u];i;i=nx[i]) { int v=to[i]; if(v!=fa[u] && v!=mxson[u]) dfs2(v,v); }}void solve(int x,int y,int op){ int C=c[x]; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); T.query(rt[C],1,n,dfn[top[x]],dfn[x],op); x=fa[top[x]]; } if(dep[x]<dep[y]) swap(x,y); T.query(rt[C],1,n,dfn[y],dfn[x],op);}char op[10];int main(){ n=read(),m=read(); for(int i=1;i<=n;++i) w[i]=read(),c[i]=read(); for(int i=1;i<n;++i) { int u=read(),v=read(); addedge(u,v); addedge(v,u); } dfs1(1,0); dfs2(1,1); for(int i=1;i<=m;++i) { scanf("%s",op); if(op[0]=='C') { if(op[1]=='C') { int x=read(),y=read(); T.upd(rt[c[x]],1,n,dfn[x],0); T.upd(rt[y],1,n,dfn[x],w[x]); c[x]=y; } else { int x=read(),y=read(); T.upd(rt[c[x]],1,n,dfn[x],y); w[x]=y; } } else { ans=0; int x=read(),y=read(); if(op[1]=='S') solve(x,y,1); else solve(x,y,0); printf("%lld\n",ans); } } return 0;}