[WC2013] 糖果公园

link

$solution:$

树上莫队模板题,树上莫队计算贡献后是除去 $u,v$ 的 $lca$ 的,简单用前缀和维护即可。

因为是带修莫队,块大小为 $n^{\frac{2}{3}}$ 时时间复杂度最小,时间复杂度 $O(n^{\frac{5}{3}})$ 。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=100001;
struct node{
    int u,v,nex;
}x[MAXN<<1];
int cnt,head[MAXN];
LL S[MAXN];
void add(int u,int v){
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int n,m,q,sta[MAXN],blo,bl[MAXN],tot,fa[MAXN][21],dep[MAXN],col[MAXN];
LL w[MAXN];
inline void dfs(int u,int fath){
    int now=sta[0];
    fa[u][0]=fath,dep[u]=dep[fath]+1;
    for(int i=1;(1<<i)<=dep[u];i++) fa[u][i]=fa[fa[u][i-1]][i-1];
    for(int i=head[u];i!=-1;i=x[i].nex){
        if(x[i].v==fath) continue;
        dfs(x[i].v,u);
        if(sta[0]-now>=blo){
            tot++;
            while(sta[0]!=now) bl[sta[sta[0]]]=tot,sta[0]--; 
        }
    }sta[++sta[0]]=u;return;
}
inline int lca(int u,int v){
    if(dep[u]<dep[v]) swap(u,v);
    for(int i=18;i>=0;i--) if(dep[u]-(1<<i)>=dep[v]) u=fa[u][i];
    if(u==v) return u;
    for(int i=18;i>=0;i--){
        if(fa[u][i]==fa[v][i]) continue;
        u=fa[u][i],v=fa[v][i];
    }return fa[u][0];
}
int Col[MAXN];
struct Query{
    int x,y,T,idx,idy,id;
    LL ans;
}query[MAXN];
struct Change{
    int x,now,las;
}change[MAXN];
bool cmp(Query x1,Query x2){
    if(x1.idx==x2.idx){
        if(x1.idy==x2.idy) return x1.T<x2.T;
        return x1.idy<x2.idy;
    }return x1.idx<x2.idx;
}
bool cmp1(Query x1,Query x2){
    return x1.id<x2.id;
}
int totq,totc,vis[MAXN];
LL Ans,Cnt[MAXN];
inline void Add(int u){
    Ans-=S[Cnt[col[u]]]*w[col[u]];
    Cnt[col[u]]++;
    Ans+=S[Cnt[col[u]]]*w[col[u]];return;
}
inline void del(int u){
    Ans-=S[Cnt[col[u]]]*w[col[u]];
    Cnt[col[u]]--;
    Ans+=S[Cnt[col[u]]]*w[col[u]];return;
}
inline void Run(int u){
    if(vis[u]){del(u),vis[u]=0;return;}
    else{Add(u);vis[u]=1;return;}
}
inline void Modify(int u,int w){
    if(vis[u]){
        del(u);
        col[u]=w;
        Add(u);
    }
    col[u]=w;return;
}
inline void move(int u,int v){
    if(dep[u]<dep[v]) swap(u,v);
    while(dep[u]>dep[v]) Run(u),u=fa[u][0];
    while(u!=v) Run(u),Run(v),u=fa[u][0],v=fa[v][0];
    return;
}
inline void solve(){
    int u=1,v=1,T=0;
    for(register int i=1;i<=totq;i++){
        while(T<query[i].T) Modify(change[T+1].x,change[T+1].now),T++;
        while(T>query[i].T) Modify(change[T].x,change[T].las),T--;
        
        move(u,query[i].x),u=query[i].x;
        move(v,query[i].y),v=query[i].y;
        int Lca=lca(u,v);
        Run(Lca),query[i].ans=Ans,Run(Lca);
    }return;
}
signed main(){
//    freopen("1.in","r",stdin);
    memset(head,-1,sizeof(head));
    n=read(),m=read(),q=read();blo=pow(n,0.45);
    for(register int i=1;i<=m;i++) w[i]=read();
    for(register int i=1;i<=n;i++) S[i]=S[i-1]+read();
    for(register int i=1;i<n;i++){
        int u=read(),v=read();
        add(u,v),add(v,u);
    }
    dfs(1,0);
    while(sta[0]) bl[sta[sta[0]]]=tot,sta[0]--;
    for(register int i=1;i<=n;i++) Col[i]=col[i]=read();
    while(q--){
        int opt=read();
        if(opt==1){
            int x=read(),y=read();
            ++totq;
            query[totq].x=x,query[totq].y=y,query[totq].T=totc,query[totq].idx=bl[x],query[totq].idy=bl[y];
            query[totq].id=totq;
        }else{
            ++totc;
            int x=read(),co=read();
            change[totc].x=x,change[totc].las=Col[x],change[totc].now=Col[x]=co;
        }
    }
    sort(query+1,query+totq+1,cmp);
    solve();
    sort(query+1,query+totq+1,cmp1);
    for(register int i=1;i<=totq;i++) printf("%lld\n",query[i].ans);return 0;
}
View Code

 

posted @ 2019-07-28 18:24  siruiyang_sry  阅读(198)  评论(0编辑  收藏  举报