糖果公园

Posted syzf2222

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了糖果公园相关的知识,希望对你有一定的参考价值。

这是树上待修莫队的裸题。

可是我已开始应为吧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;
} 

总体来说还是挺好写的,毕竟我都是两遍就过了……

深深地感到自己的弱小。

以上是关于糖果公园的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3052 糖果公园

WC2013 糖果公园 - 树上莫队

[WC2013][UOJ58]糖果公园 莫队算法

[BZOJ3052][UOJ#58][WC2013]糖果公园

BZOJ 3052: [wc2013]糖果公园 | 树上莫队

[Luogu4074][WC2013]糖果公园