传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3531
考场上爆零,发奋学链剖,然后水过……
感谢GreenClouds神犇教我的动态开点的线段树
递归的链剖会在链的时候爆栈,蒟蒻YY了一个非递归的,见代码
Code:
#include<cstdio> #include<stack> #include<deque> #include<vector> #include<iostream> #include<algorithm> #define X first #define Y second using namespace std; const int maxn=100100; vector<int>G[maxn]; typedef pair<int,int> pii; void add(int u,int v){ G[u].push_back(v); G[v].push_back(u); } int top[maxn],w[maxn],fa[maxn],son[maxn],siz[maxn],dep[maxn],z=0; int n,q; int W[maxn],C[maxn]; //递归版 /* void dfs(const int &u){ son[u]=0;siz[u]=1; for(int i=0;i<G[u].size();i++){ const int &v=G[u][i]; if(v!=fa[u]){ fa[v]=u; dep[v]=dep[u]+1; dfs(v); if(siz[son[u]]<siz[v])son[u]=v; siz[u]+=siz[v]; } } }*/ //GTY神犇版 /* inline void dfs(int root,int BigBoss) { memset(cur,-1,sizeof(cur)); int now=root; while (now!=f[root]) { if (cur[now]==-1) { cur[now]=point[now]; boss[now]=BigBoss; bossson[BigBoss]++; NewSon(now); } else cur[now]=next[cur[now]]; if (cur[now]&&v[cur[now]]==f[now]) cur[now]=next[cur[now]]; if (!cur[now]) { now=f[now]; continue; } f[v[cur[now]]]=now; now=v[cur[now]]; } }*/ //YY的非递归#1 int order[maxn]; stack<int>S; void dfs(int u){ S.push(u); order[0]=0; while(!S.empty()){ int u=S.top();S.pop(); son[u]=0;siz[u]=1; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v!=fa[u]){ dep[v]=dep[u]+1; fa[v]=u; S.push(v); order[++order[0]]=v; } } } for(int i=order[0];i>=1;i--){ int u=order[i]; if(siz[son[fa[u]]]<siz[u])son[fa[u]]=u; siz[fa[u]]+=siz[u]; } } //递归版 /* void build(int u,int tp){ w[u]=++z;top[u]=tp; if(son[u])build(son[u],tp); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v!=fa[u]&&v!=son[u])build(v,v); } }*/ //YY的非递归#2 deque<pii>Q; void build(int u,int tp){ Q.push_front(pii(u,tp)); while(!Q.empty()){ pii t=Q.front();Q.pop_front(); int u=t.X,tp=t.Y; w[u]=++z;top[u]=tp; if(son[u])Q.push_front(pii(son[u],tp)); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v!=fa[u]&&v!=son[u]) Q.push_back(pii(v,v)); } } } int V=0; struct seg_tree{ struct node{ int l,r,sum,m; node(){l=0;r=0;sum=0;m=0;} }; node t[3010000]; void rz(int x){ t[x].sum=t[t[x].l].sum+t[t[x].r].sum; t[x].m=max(t[t[x].l].m,t[t[x].r].m); } void change(int l,int r,int pos,int val,int &c){ if(l>r)return; if(!c)c=++V; if(l==r){ t[c].sum=t[c].m=val; return; }int mid=l+r>>1; if(pos<=mid)change(l,mid,pos,val,t[c].l); else change(mid+1,r,pos,val,t[c].r); rz(c); } int qsum(int l,int r,int l0,int r0,int &c){ if(c==0)return 0; if(l>r)return 0; if(l0<=l&&r0>=r) return t[c].sum; int mid=l+r>>1; int ans=0; if(l0<=mid)ans+=qsum(l,mid,l0,r0,t[c].l); if(r0>mid) ans+=qsum(mid+1,r,l0,r0,t[c].r); return ans; } int qmax(int l,int r,int l0,int r0,int &c){ if(c==0)return 0; if(l>r)return 0; if(l0<=l&&r0>=r) return t[c].m; int mid=l+r>>1; int ans=0; if(l0<=mid)ans=max(ans,qmax(l,mid,l0,r0,t[c].l)); if(r0>mid) ans=max(ans,qmax(mid+1,r,l0,r0,t[c].r)); return ans; } }T; int Tr[maxn]; void CC(int x,int c){ T.change(1,n,w[x],0,Tr[C[x]]); C[x]=c; T.change(1,n,w[x],W[x],Tr[C[x]]); } void CW(int x,int ww){ W[x]=ww; T.change(1,n,w[x],ww,Tr[C[x]]); } int QS(int u,int v){ int ans=0;int c=C[u]; while(top[u]!=top[v]){ if(dep[top[u]]>dep[top[v]]){ int a=w[u],b=w[top[u]]; if(a>b)swap(a,b); ans+=T.qsum(1,n,a,b,Tr[c]); u=fa[top[u]]; }else{ int a=w[v],b=w[top[v]]; if(a>b)swap(a,b); ans+=T.qsum(1,n,a,b,Tr[c]); v=fa[top[v]]; } } int a=w[u],b=w[v]; if(a>b)swap(a,b); ans+=T.qsum(1,n,a,b,Tr[c]); return ans; } int QM(int u,int v){ int ans=0;int c=C[u]; while(top[u]!=top[v]){ if(dep[top[u]]>dep[top[v]]){ int a=w[u],b=w[top[u]]; if(a>b)swap(a,b); ans=max(ans,T.qmax(1,n,a,b,Tr[c])); u=fa[top[u]]; }else{ int a=w[v],b=w[top[v]]; if(a>b)swap(a,b); ans=max(ans,T.qmax(1,n,a,b,Tr[c])); v=fa[top[v]]; } } int a=w[u],b=w[v]; if(a>b)swap(a,b); ans=max(ans,T.qmax(1,n,a,b,Tr[c])); return ans; } int main(){ // freopen("Q3.in","r",stdin); scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d%d",&W[i],&C[i]); for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v); }dfs(1);build(1,1); for(int i=1;i<=n;i++){ CC(i,C[i]); CW(i,W[i]); } while(q--){ int x,y,c,w; char opt[2]; scanf("%s",opt); if(opt[0]=='C'&&opt[1]=='C'){ scanf("%d%d",&x,&c); CC(x,c); }else if(opt[0]=='C'&&opt[1]=='W'){ scanf("%d%d",&x,&w); CW(x,w); }else if(opt[0]=='Q'&&opt[1]=='S'){ scanf("%d%d",&x,&y); printf("%d\n",QS(x,y)); }else if(opt[0]=='Q'&&opt[1]=='M'){ scanf("%d%d",&x,&y); printf("%d\n",QM(x,y)); } } return 0; }