[WC2013] 糖果公园

Posted si-rui-yang

tags:

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

link

$solution:$

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

因为是待修莫队,块大小为 $n^\frac23$ 时最小,时间复杂度 $O(n^\frac53)$ 。

技术图片
#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;
    elseAdd(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

 

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

WC2013 糖果公园 - 树上莫队

WC2013 糖果公园

「WC2013」糖果公园

[bzoj 3052][wc2013]糖果公园

[WC2013]糖果公园

BZOJ3052: [wc2013]糖果公园 树分块+待修改莫队算法