这是树上待修莫队的裸题。
可是我已开始应为吧cmp写错了TLE成30,呜呜……
看代码:
#include<bits/stdc++.h> using namespace std; #define int long long const int maxn=1e5+10; int n,m,q,a[maxn<<1],fir[maxn],las[maxn],top; int v[maxn],w[maxn]; int beg[maxn],nex[maxn<<1],to[maxn<<1],e; inline void add(int x,int y){ e++;nex[e]=beg[x]; beg[x]=e;to[e]=y; } inline int read(){ int x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<1)+(x<<3)+c-'0'; c=getchar(); } return x*f; } int dep[maxn],f[maxn][20],c[maxn]; inline void dfs(int x,int fa){ a[++top]=x; fir[x]=top; dep[x]=dep[fa]+1; f[x][0]=fa; for(int i=1;i<=19;i++) f[x][i]=f[f[x][i-1]][i-1]; for(int i=beg[x];i;i=nex[i]) if(to[i]!=fa)dfs(to[i],x); a[++top]=x; las[x]=top; } inline int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); for(int i=19;i>=0;i--) if(dep[x]-(1<<i)>=dep[y]) x=f[x][i]; if(x==y)return x; for(int i=19;i>=0;i--) if(f[x][i]!=f[y][i]){ x=f[x][i]; y=f[y][i]; } return f[x][0]; } struct change{ int pos,col; }ch[maxn]; struct query{ int l,r,bl,br,lca,id,cha; }que[maxn]; inline int cmp(query x,query y){ return (x.bl^y.bl)?(x.bl<y.bl):((x.br^y.br)?(x.br<y.br):((x.br&1)?(x.cha<y.cha):(x.cha>y.cha))); } int vis[maxn],now,cnt[maxn]; inline void dele(int x){ if(!vis[x])now+=v[c[x]]*w[++cnt[c[x]]]; else now-=v[c[x]]*w[cnt[c[x]]--]; vis[x]^=1; } int ans[maxn]; signed main(){ n=read(),m=read(),q=read(); int len=pow(n,2.0/3.0); for(int i=1;i<=m;i++) v[i]=read(); for(int i=1;i<=n;i++) w[i]=read(); int opt,x,y; for(int i=1;i<n;i++){ x=read(),y=read(); add(x,y),add(y,x); } dfs(1,0); for(int i=1;i<=n;i++) c[i]=read(); int t1=0,t2=0; for(int i=1;i<=q;i++){ opt=read(),x=read(),y=read(); if(opt==0){ t1++; ch[t1].pos=x; ch[t1].col=y; }else{ t2++; que[t2].id=t2; que[t2].cha=t1; if(dep[x]>dep[y])swap(x,y); if(lca(x,y)==x){ que[t2].l=fir[x]; que[t2].r=fir[y]; }else{ que[t2].l=las[x]; que[t2].r=fir[y]; que[t2].lca=lca(x,y); } que[t2].bl=que[t2].l/len; que[t2].br=que[t2].r/len; } } sort(que+1,que+1+t2,cmp); int l=1,r=0,ti=0; for(int i=1;i<=t2;i++){ while(l<que[i].l)dele(a[l++]); while(l>que[i].l)dele(a[--l]); while(r<que[i].r)dele(a[++r]); while(r>que[i].r)dele(a[r--]); while(ti<que[i].cha){ ti++; if(vis[ch[ti].pos]){ now-=v[c[ch[ti].pos]]*w[cnt[c[ch[ti].pos]]--]; now+=v[ch[ti].col]*w[++cnt[ch[ti].col]]; }swap(ch[ti].col,c[ch[ti].pos]); } while(ti>que[i].cha){ if(vis[ch[ti].pos]){ now-=v[c[ch[ti].pos]]*w[cnt[c[ch[ti].pos]]--]; now+=v[ch[ti].col]*w[++cnt[ch[ti].col]]; }swap(ch[ti].col,c[ch[ti].pos]); ti--; } if(que[i].lca)dele(que[i].lca); ans[que[i].id]=now; if(que[i].lca)dele(que[i].lca); } for(int i=1;i<=t2;i++) printf("%lld ",ans[i]); return 0; }
总体来说还是挺好写的,毕竟我都是两遍就过了……
深深地感到自己的弱小。