分析
首先先推荐一篇关于莫队的博客
这个题我们不难看出就是树上带修莫队
一直在犯sb错误,调了好长时间嘤嘤嘤
代码
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cctype> #include<cmath> #include<cstdlib> #include<queue> #include<ctime> #include<vector> #include<set> #include<map> #include<stack> using namespace std; #define li long long const int LOG = 20; int n,m,q,val[100100],w[100100],now[100100],t1,t2,belong[300100]; li ans[100100],Ans; int pr[100100][23],N,dfn[300100],beg[300100],fin[300100],dep[100100]; int sum[100100],vis[100100],L,R,T; vector<int>v[100100]; struct node { int x,y,t,ano,pl; }; node d[100100]; struct iint { int x,y,la; }; iint a[100100]; inline void dfs(int x,int fa){ dep[x]=dep[fa]+1; for(int i=0;i<v[x].size();++i) if(v[x][i]!=fa){ pr[v[x][i]][0]=x; dfs(v[x][i],x); } } inline void dfs2(int x,int fa){ dfn[++N]=x; for(int i=0;i<v[x].size();++i) if(v[x][i]!=fa)dfs2(v[x][i],x); dfn[++N]=x; } inline int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); for(int i=LOG;i>=0;--i) if(dep[pr[x][i]]>=dep[y])x=pr[x][i]; if(x==y)return x; for(int i=LOG;i>=0;--i) if(pr[x][i]!=pr[y][i]) x=pr[x][i],y=pr[y][i]; return pr[x][0]; } inline bool cmp(const node &x,const node &y){ if(belong[x.x]==belong[y.x]){ if(x.y==y.y)return x.t<y.t; return x.y<y.y; } return x.x<y.x; } inline void add(int x){ sum[now[x]]++; Ans+=(li)w[sum[now[x]]]*val[now[x]]; } inline void deal(int x){ Ans-=(li)w[sum[now[x]]]*val[now[x]]; sum[now[x]]--; } inline void go(int x,int k){ int u=(k?x:dfn[x]); vis[u]^=1; if(vis[u])add(u); else deal(u); } inline void goago(int x){ int u=a[x].x; if(vis[u])deal(u); now[u]=a[x].la; if(vis[u])add(u); } inline void gonxt(int x){ int u=a[x].x; a[x].la=now[u]; if(vis[u])deal(u); now[u]=a[x].y; if(vis[u])add(u); } inline int ra(){ int x=0;char s=getchar(); while(!isdigit(s))s=getchar(); while(isdigit(s))x=(x<<3)+(x<<1)+(s-'0'),s=getchar(); return x; } int main(){ int i,j,k,x,y; n=ra(),m=ra(),q=ra(); for(i=1;i<=m;++i)val[i]=ra(); for(i=1;i<=n;++i)w[i]=ra(); for(i=1;i<n;++i){ x=ra(),y=ra(); v[x].push_back(y); v[y].push_back(x); } for(i=1;i<=n;++i)now[i]=ra(); for(i=1;i<=q;++i){ k=ra(),x=ra(),y=ra(); if(k){ d[++t1].x=x; d[t1].y=y; d[t1].t=t2; d[t1].pl=t1; }else { a[++t2].x=x; a[t2].y=y; } } pr[1][0]=0; dfs(1,0); for(i=1;i<=LOG;++i) for(j=1;j<=n;++j) pr[j][i]=pr[pr[j][i-1]][i-1]; dfs2(1,0); for(i=1;i<=N;++i) if(!beg[dfn[i]])beg[dfn[i]]=i; for(i=N;i>0;i--) if(!fin[dfn[i]])fin[dfn[i]]=i; for(i=1;i<=t1;++i){ x=d[i].x,y=d[i].y; if(beg[x]>beg[y])swap(x,y); k=lca(x,y); if(x==k)d[i].x=min(fin[x],fin[y]),d[i].y=max(fin[y],fin[x]),d[i].ano=-1; else d[i].x=beg[x]+1,d[i].y=fin[y]-1,d[i].ano=k; } double block=pow((double)N,2.0/3); int B=block; for(i=1;i<=N;++i) belong[i]=(i-1)/B+1; sort(d+1,d+t1+1,cmp); L=1,R=0,T=0; for(i=1;i<=t1;++i){ while(T>d[i].t){ goago(T); T--; } while(T<d[i].t){ T++; gonxt(T); } while(R>d[i].y){ go(R,0); R--; } while(R<d[i].y){ R++; go(R,0); } while(L>d[i].x){ L--; go(L,0); } while(L<d[i].x){ go(L,0); L++; } if(d[i].ano!=-1)go(d[i].ano,1); ans[d[i].pl]=Ans; if(d[i].ano!=-1)go(d[i].ano,1); } for(i=1;i<=t1;++i) printf("%lld\n",ans[i]); return 0; }