UOJ#58. 【WC2013】糖果公园
分析
首先先推荐一篇关于莫队的博客
这个题我们不难看出就是树上带修莫队
一直在犯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;
}