bzoj3052 [wc2013]糖果公園(樹上莫隊,帶修改)
阿新 • • 發佈:2019-01-25
樹上莫隊參見spoj_cot2,帶修改莫隊參見bzoj2120.這道題就是把這倆和在一起了╭(╯^╰)╮。bzoj上時間很寬鬆。。大家如果沒把握還是不要去爆oj了的好。給大家推薦個好地方UOJ,這題的題號是58。可以先在那過了再說。。uoj的評測機好好的說。。順便我樹上莫隊也是從建了uoj的vfk那裡學來的。。大家可以去搜一下他的部落格。我在這裡放連結是不是算侵權??不懂。。只能orz神犇。(因為打錯變數調了一下午的我,欲哭無淚。辣雞樣例,打錯變數都能過。。)
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define ll long long #define N 100005 using namespace std; int n,m,qq,block,a[N],h[N],num=0,now=0,prev[N]; int fa[N][18],dep[N],stack[N],top=0,dfn_num=0,dfn[N]; int f[N],Log[N],tot=0,block_num=0,belong[N]; ll w[N],ans=0,ANS[N],v[N]; bool vis[N]; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } inline int swap(int &x,int &y){x^=y;y^=x;x^=y;} struct edge{ int to,next; }data[N<<1]; struct timeflow{ int pre,to,pos; }modify[N]; struct query{ int l,r,id,timen; }q[N]; inline int cmp(query x,query y){ if(belong[x.l]==belong[y.l]){ return dfn[x.r]==dfn[y.r]?x.timen<y.timen:dfn[x.r]<dfn[y.r]; }else return belong[x.l]<belong[y.l]; } inline int dfs(int x){ dfn[x]=++dfn_num;int size=0; for(int i=1;i<=Log[dep[x]];++i) fa[x][i]=fa[fa[x][i-1]][i-1]; for(int i=h[x];i;i=data[i].next){ int y=data[i].to; if(y==fa[x][0]) continue; fa[y][0]=x;dep[y]=dep[x]+1; size+=dfs(y); if(size>=block){ ++block_num; while(size--) belong[stack[top--]]=block_num; } } stack[++top]=x; return size+1; } inline void change(int x,int y){ if(vis[x]){ ans-=w[f[a[x]]]*v[a[x]];f[a[x]]--; a[x]=y; f[a[x]]++;ans+=w[f[a[x]]]*v[a[x]]; } else a[x]=y; } inline int lca(int x,int y){ if(dep[x]<dep[y]) swap(x,y); int d=dep[x]-dep[y]; for(int i=0;i<=Log[d];++i) if(d&(1<<i)) x=fa[x][i]; if(x==y) return x; for(int i=Log[n];i>=0;--i) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } inline void reverse(int x){ if(vis[x]) ans-=w[f[a[x]]]*v[a[x]],f[a[x]]--; else f[a[x]]++,ans+=w[f[a[x]]]*v[a[x]]; vis[x]^=1; } inline void solve(int x,int y){ while(x!=y){ if(dep[x]>dep[y]) reverse(x),x=fa[x][0]; else reverse(y),y=fa[y][0]; } } int main(){ // freopen("a.in","r",stdin); n=read();m=read();qq=read();block=pow(n,2.0/3)*0.5; for(int i=1;i<=m;++i) v[i]=read(); for(int i=1;i<=n;++i) w[i]=read(); for(int i=1;i<n;++i){ int x=read(),y=read(); data[++num].to=y;data[num].next=h[x];h[x]=num; data[++num].to=x;data[num].next=h[y];h[y]=num; } for(int i=1;i<=n;++i) prev[i]=a[i]=read(); Log[0]=-1;for(int i=1;i<=n;++i) Log[i]=Log[i>>1]+1; dep[1]=1;dfs(1);++block_num; while(top) belong[stack[top--]]=block_num; while(qq--){ int op=read(),x=read(),y=read(); if(!op){ modify[++now].pre=prev[x];prev[x]=y; modify[now].to=y;modify[now].pos=x; } else{ q[++tot].l=x;q[tot].r=y;q[tot].timen=now;q[tot].id=tot; if(belong[x]>belong[y]) swap(q[tot].l,q[tot].r); } }sort(q+1,q+tot+1,cmp); for(int i=1;i<=q[1].timen;++i) a[modify[i].pos]=modify[i].to; solve(q[1].l,q[1].r);int t=lca(q[1].l,q[1].r); ANS[q[1].id]=ans+v[a[t]]*(w[f[a[t]]+1]); for(int i=2;i<=tot;++i){ for(int j=q[i-1].timen;j>q[i].timen;--j) change(modify[j].pos,modify[j].pre); for(int j=q[i-1].timen;j<q[i].timen;++j) change(modify[j+1].pos,modify[j+1].to); solve(q[i-1].l,q[i].l);solve(q[i-1].r,q[i].r); int t=lca(q[i].l,q[i].r);ANS[q[i].id]=ans+v[a[t]]*(w[f[a[t]]+1]); } for(int i=1;i<=tot;++i) printf("%lld\n",ANS[i]); return 0; }