http://www.lydsy.com/JudgeOnline/problem.php?id=3052
树上带修莫队棵题
写完了,吐了一口老血
#include<cstdio> #include<algorithm> #include<cmath> #define VIS(now) for(register int e=las[now];e;e=nxt[e]) #define FOR(i,s,t) for(register int i=s;i<=t;++i) typedef long long ll; using std::swap; using std::sort; const int N=200011; int xu[N],v[N],w[N],a[N],hv[N]; int las[N],nxt[N],to[N],bo[N]; int dep[N],top[N],sz[N],fa[N]; int blo,dfn_num,tot,times; int n,m,Q; ll res; ll ans[N]; inline void add(int x,int y){ nxt[++tot]=las[x];las[x]=tot;to[tot]=y; } struct qs{ int l,r,t,id; inline bool operator<(qs A)const{ if(xu[l]/blo!=xu[A.l]/blo)return xu[l]<xu[A.l]; if(xu[r]/blo!=xu[A.r]/blo)return xu[r]<xu[A.r]; if(t/blo!=A.t/blo)return t<A.t; return id<A.id; } }q[N]; struct cg{int p,x;}c[N]; inline void dfs1(int now){ sz[now]=1; VIS(now) if(!dep[to[e]]){ dep[to[e]]=dep[now]+1;fa[to[e]]=now; dfs1(to[e]);sz[now]+=sz[to[e]]; } } inline void dfs2(int now,int chain){ xu[now]=++dfn_num;top[now]=chain; register int i=0; VIS(now)if(sz[to[e]]>sz[i]&&fa[now]!=to[e])i=to[e]; if(!i)return;dfs2(i,chain); VIS(now)if(to[e]!=fa[now]&&to[e]!=i)dfs2(to[e],to[e]); } inline int LCA(int x,int y){ for(;top[x]!=top[y];dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]); return dep[x]<dep[y]?x:y; } int t,x,y,l,r,now,lca; inline void add(int x){ bo[x]^=1; if(bo[x]) ++hv[a[x]],res+=1ll*w[hv[a[x]]]*v[a[x]]; else res-=1ll*w[hv[a[x]]]*v[a[x]],--hv[a[x]]; } inline void change(int t){ int pos=c[t].p; if(bo[pos]){ res-=1ll*w[hv[a[pos]]]*v[a[pos]],--hv[a[pos]]; ++hv[c[t].x],res+=1ll*w[hv[c[t].x]]*v[c[t].x]; } swap(a[pos],c[t].x); } int main(){ scanf("%d%d%d",&n,&m,&Q); blo=pow(n,2.00/3.00); FOR(i,1,m)scanf("%d",v+i); FOR(i,1,n)scanf("%d",w+i); FOR(i,2,n)scanf("%d%d",&x,&y),add(x,y),add(y,x); FOR(i,1,n)scanf("%d",a+i); dep[1]=1;dfs1(1);dfs2(1,1); tot=0; FOR(i,1,Q){ scanf("%d%d%d",&t,&x,&y); if(t==1){ if(xu[x]>xu[y])swap(x,y); q[++tot]=(qs){x,y,times,tot}; } else c[++times]=(cg){x,y}; } sort(q+1,q+tot+1); l=1,r=1,now=0; FOR(i,1,tot){ lca=LCA(l,q[i].l); for(register int j=l;j!=lca;j=fa[j])add(j); for(register int j=q[i].l;j!=lca;j=fa[j])add(j); lca=LCA(r,q[i].r); for(register int j=r;j!=lca;j=fa[j])add(j); for(register int j=q[i].r;j!=lca;j=fa[j])add(j); lca=LCA(q[i].l,q[i].r); add(lca); while(now<q[i].t)change(++now); while(now>q[i].t)change(now--); ans[q[i].id]=res; add(lca); l=q[i].l;r=q[i].r; } FOR(i,1,tot)printf("%lld ",ans[i]); return 0; }