线段树动态开点或者平衡树。卡常没卡过。。。。。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<ctime> #define maxn 500050 #define maxv 500050 #define maxe 200050 using namespace std; int n,m,x,y,z,g[maxv],nume=0,fath[maxv],top[maxv],dis[maxv],size[maxv],son[maxv],times=0,fa[maxv]; int root[maxv],c[maxn],val[maxn],w[maxn],mx[maxn],sum[maxn],tot,reg=0,tree[maxn][3],pre,sub; char type[4]; struct edge { int v,nxt; }e[maxe]; struct io_t{ char op[1<<23]; char* s; io_t():s(op){ s[ fread(s,1, sizeof op,stdin) ] = 0; } void scan(char* q){ while(*s<48) ++s; while(*s>32) *q++=*s++; *q=0; } int scan(){ static int v,j; v=0,j=1; while(*s<48) j=*s++^45; do v=v*10+*s++-48; while(*s>32); return j?v:-v; } }io; #define read io.scan void addedge(int u,int v) { e[++nume].v=v; e[nume].nxt=g[u]; g[u]=nume; } void get_info() { n=read();m=read();tot=n; for (int i=1;i<=n;i++) {val[i]=read();c[i]=read();reg=max(reg,c[i]);} for (int i=1;i<=100000;i++) {root[i]=++tot;tree[root[i]][2]=++tot;fath[tot]=root[i];w[tot]=n+1;} for (int i=1;i<=n-1;i++) { x=read();y=read(); addedge(x,y);addedge(y,x); } } void dfs1(int x) { size[x]=1;son[x]=0; for (int i=g[x];i;i=e[i].nxt) { int v=e[i].v; if (v!=fa[x]) { fa[v]=x;dis[v]=dis[x]+1; dfs1(v); size[x]+=size[v]; if (size[v]>size[son[x]]) son[x]=v; } } } void dfs2(int x,int father) { top[x]=father;w[x]=++times; if (son[x]) dfs2(son[x],father); for (int i=g[x];i;i=e[i].nxt) { int v=e[i].v; if (v!=fa[x] && v!=son[x]) dfs2(v,v); } } void tree_cut() {dfs1(1);dfs2(1,1);} void pushup(int now) { sum[now]=sum[tree[now][1]]+sum[tree[now][2]]+val[now]; mx[now]=max(val[now],max(mx[tree[now][1]],mx[tree[now][2]])); } void insert(int &now,int father,int x) { if (!now) { now=x;fath[now]=father;tree[now][1]=tree[now][2]=0; sum[now]=mx[now]=val[now]; return; } if (w[x]<w[now]) insert(tree[now][1],now,x); else insert(tree[now][2],now,x); pushup(now); } void rotate(int x,int &k) { int y=fath[x],z=fath[y],l,r; if (tree[y][1]==x) l=1;else l=2;r=3-l; if (y==k) k=x; else { if (tree[z][1]==y) tree[z][1]=x; else tree[z][2]=x; } fath[x]=z;fath[y]=x;fath[tree[x][r]]=y; tree[y][l]=tree[x][r];tree[x][r]=y; pushup(y);pushup(x); } void splay(int x,int &k) { while (x!=k) { int y=fath[x],z=fath[y]; if (y!=k) { if ((tree[z][1]==y)^(tree[y][1]==x)) rotate(x,k); else rotate(y,k); } rotate(x,k); } } void build_tree() { for (int i=1;i<=n;i++) { insert(root[c[i]],0,i); splay(i,root[c[i]]); } } void get_pre(int now,int x) { if (!now) return; if (w[now]<x) {pre=now;get_pre(tree[now][2],x);} else get_pre(tree[now][1],x); } void get_sub(int now,int x) { if (!now) return; if (w[now]>x) {sub=now;get_sub(tree[now][1],x);} else get_sub(tree[now][2],x); } void delete_(int x) { get_pre(root[c[x]],w[x]);get_sub(root[c[x]],w[x]); splay(pre,root[c[x]]);splay(sub,tree[root[c[x]]][2]); int now=tree[root[c[x]]][2]; tree[now][1]=fath[x]=tree[x][1]=tree[x][2]=0;pushup(now);pushup(root[c[x]]); } int ask(int c,int l,int r,int type) { get_pre(root[c],l);get_sub(root[c],r); splay(pre,root[c]); splay(sub,tree[root[c]][2]); int now=tree[tree[root[c]][2]][1]; if (type==1) return sum[now]; else return mx[now]; } void get_ans(int x,int y,int type,int c) { int ans=0; int f1=top[x],f2=top[y]; while (f1!=f2) { if (dis[f1]<dis[f2]) {swap(f1,f2);swap(x,y);} if (type==1) ans+=ask(c,w[f1],w[x],1); else ans=max(ans,ask(c,w[f1],w[x],2)); x=fa[f1];f1=top[x]; } if (dis[x]>dis[y]) swap(x,y); if (type==1) ans+=ask(c,w[x],w[y],1); else ans=max(ans,ask(c,w[x],w[y],2)); printf("%d\n",ans); } void work() { for (int i=1;i<=m;i++) { read( type ); if ((type[0]=='C') && (type[1]=='C')) { x=read();y=read(); delete_(x);c[x]=y; insert(root[c[x]],0,x); splay(x,root[c[x]]); } else if ((type[0]=='C') && (type[1]=='W')) { x=read();y=read(); splay(x,root[c[x]]);val[x]=y;pushup(x); } else if ((type[0]=='Q') && (type[1]=='S')) {x=read();y=read();get_ans(x,y,1,c[y]);} else {x=read();y=read();get_ans(x,y,2,c[y]);} } } int main() { get_info(); tree_cut(); build_tree(); work(); return 0; }