zoukankan      html  css  js  c++  java
  • 【WC2013】糖果公园 [树上莫队]

    题意:

    一棵树,修改一个点的颜色,询问两点路径上每种颜色的权值$val[c]$*出现次数的权值$cou[w[c]]$的和


    sro VFK 

    树上莫队

    按照王室联邦的方法分块,块的大小直径个数有保证,并不需要连通

    和带修改莫队一样按照$(pos[u],pos[v],tim)$排序

    维护$u,v,cur$三个点,以及每个节点的访问状态$vis[]$,每种颜色出现次数$cou[]$,当前答案$now$

    如何移动?

    时间移动和序列上一样

    $u,v$移动到$u,v'$

    $Path(u,v)=Path(u,root) oplus Path(v,root) oplus lca(u,v)$

    先不管$lca$,令$T(u,v)=Path(u,root) oplus Path(v,root)$

    $T(u,v')=Path(u,root) oplus Path(v',root)$

    经计算$T(u,v')=T(u,v) oplus T(v,v')$

    画一下图很好理解

    所以移动的时候我们只要更新$v$到$v'$路径上除去$lca$的所有点就可以了,最后对于每个询问额外把$lca(u,v)$加上

    分块大小貌似稍小一点比较好

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n,k,Q,a[N],t[N],op,x,y, val[N];
    ll w[N];
    
    struct edge{int v,ne;} e[N<<1];
    int cnt,h[N];
    inline void ins(int u,int v){
        e[++cnt]=(edge){v,h[u]}; h[u]=cnt;
        e[++cnt]=(edge){u,h[v]}; h[v]=cnt;
    }
    int block,m,pos[N];
    int st[N],top;
    void dfs(int u,int fa){
        int bot=top;
        for(int i=h[u];i;i=e[i].ne) if(e[i].v!=fa){
            dfs(e[i].v, u);
            if(top-bot>=block){
                m++;
                while(top!=bot) pos[st[top--]]=m;
            }
        }
        st[++top]=u;
    }
    
    int fa[N][20], deep[N];
    void dfs(int u){
        for(int i=1; (1<<i)<=deep[u]; i++)
            fa[u][i]=fa[ fa[u][i-1] ][i-1];
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].v!=fa[u][0]){
                deep[ e[i].v ]=deep[u]+1;
                fa[ e[i].v ][0]=u;
                dfs(e[i].v);
            }
    }
    inline int lca(int x,int y){
        if(deep[x]<deep[y]) swap(x, y);
        int bin=deep[x]-deep[y];
        for(int i=0;i<17;i++) if((1<<i)&bin) x=fa[x][i];
        for(int i=17;i>=0;i--) 
            if(fa[x][i]!=fa[y][i]) x=fa[x][i], y=fa[y][i];
        return x==y ? x : fa[x][0];
    }
    
    struct cmeow{int u,next,last;} cq[N];
    struct meow{
        int u,v,tim,id;
        bool operator <(const meow &a) const {
            return pos[u]==pos[a.u] ? (pos[v]==pos[a.v] ? tim<a.tim : pos[v]<pos[a.v]) : pos[u]<pos[a.u];
        }
    }q[N];
    int p,tim,u,v,cur; ll now,ans[N];
    int vis[N], cou[N]; 
    inline void cha(int u,int d){ 
        int &c=a[u];
        if(vis[u]){
            now-= w[cou[c]] * val[c]; now-= w[cou[d]] * val[d];
            cou[c]--; cou[d]++;
            now+= w[cou[c]] * val[c]; now+= w[cou[d]] * val[d];
        }
        c=d;
    }
    inline void Xor(int u){
        int c=a[u];
        now-= w[cou[c]] * val[c];
        vis[u] ? cou[c]-- : cou[c]++;  vis[u]^=1;
        now+= w[cou[c]] * val[c];
    }
    void move(int x,int y){ 
        if(deep[x]<deep[y]) swap(x, y);
        while(deep[x]>deep[y]) Xor(x), x=fa[x][0];// printf("%d %lld
    ",x,now);
        while(x!=y) Xor(x), Xor(y), x=fa[x][0], y=fa[y][0];
    }
    void modui(){
        u=1; v=1;
        for(int i=1;i<=p;i++){
            while(cur<q[i].tim) cur++, cha(cq[cur].u, cq[cur].next);
            while(cur>q[i].tim) cha(cq[cur].u, cq[cur].last), cur--;
            if(u!=q[i].u) move(u, q[i].u), u=q[i].u;
            if(v!=q[i].v) move(v, q[i].v), v=q[i].v;
    
            int anc=lca(u, v);
            Xor(anc); ans[q[i].id]= now; Xor(anc);
        }
    }
    int main(){
        freopen("in","r",stdin);
        n=read(); k=read(); Q=read();
        for(int i=1;i<=k;i++) val[i]=read();
        for(int i=1;i<=n;i++) w[i]=read()+w[i-1];
        for(int i=1;i<n ;i++) ins(read(), read() );
        for(int i=1;i<=n;i++) a[i]=t[i]=read();
    
        block=pow(n,(double)1.9/3);
        dfs(1, 0);
        while(top) pos[st[top--]]=m;
        dfs(1);
    
        for(int i=1;i<=Q;i++){
            op=read(); x=read(); y=read();
            if(op) p++,q[p]=(meow){x,y,tim,p};
            else tim++,cq[tim]=(cmeow){x,y,t[x]}, t[x]=y;
        }
        sort(q+1, q+1+p);
        modui();
        for(int i=1;i<=p;i++) printf("%lld
    ", ans[i]);
    }
  • 相关阅读:
    ios属性或者变量的前缀-杂记
    xcode注释方法
    ios 不同的数据类型转化为json类型
    第一部分----HTML的基本结构与基本标签
    Git使用总结
    c#后台弹出框
    svn下载安装
    svn配置
    access 日期转换
    C# 中关于汉字与16进制转换的代码
  • 原文地址:https://www.cnblogs.com/candy99/p/6572644.html
Copyright © 2011-2022 走看看