zoukankan      html  css  js  c++  java
  • BZOJ 4817数点涂色题解

    题目链接

    考试考了一道类似的题目,然后不争气的挂掉了,于是跑过来学习这道题的解法...

    我还是太菜了....

    我们可以发现任意时刻,原树中颜色相同的点的集合一定是一条链,

    即上面这种状态,而这种结构是不是跟某种毒瘤数据结构很想,没错,就是LCT

    我们发现LCT中的每一颗splay对应着每一段颜色的链

    修改节点x到根的颜色时,只需要access一下就好了

    我们再考虑每一次修改时对答案的影响

    每一个节点到根的权值记作f[i],显然f[i]就是i节点到根节点所经过的轻边数目加1

    我们再利用一颗线段树维护dfs序上的f[]数组,方便查询

    我们access是每次将虚边变为实边是就将那颗子树中的f[]数组减一

    每次实边边虚边就加一

    操作三的答案可以通过dfs序查询子树最大

    而操作二的答案可很容易发现就是f[x]+f[y]-2*f[lca(x,y)]+1

    一样维护一下就好了

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    
    using namespace std;
    
    const int mn = 1e5 + 10;
    const int inf = 0x3f3f3f3f;
    
    struct edge{int to,next;};
    edge e[mn*2];
    int head[mn],edge_max,n,m;
    int mx[mn*4],tag[mn*4];
    int fa[mn],in[mn],out[mn],deep[mn],id[mn],clo,siz[mn],bl[mn];
    
    void add(int x,int y)
    {
        e[++edge_max].to=y;
        e[edge_max].next=head[x];
        head[x]=edge_max;
    }
    
    void dfs(int x)
    {
        siz[x]=1;
        in[x]=++clo;
        id[clo]=x;
        for(int i=head[x]; i; i=e[i].next)
        {
            if(e[i].to==fa[x]) continue;
            fa[e[i].to]=x;
            deep[e[i].to]=deep[x]+1;
            dfs(e[i].to);
            siz[x]+=siz[e[i].to];
        }
        out[x]=clo;
    }
    
    void dfs2(int x,int chain)
    {
        bl[x]=chain;
        int k=0;
        for(int i=head[x]; i; i=e[i].next)
        {
            if(e[i].to!=fa[x] && siz[e[i].to]>siz[k])
                k=e[i].to;
        }
        if(!k) return ;
        dfs2(k,chain);
        for(int i=head[x]; i; i=e[i].next)
        {
            if(e[i].to!=fa[x] && e[i].to!=k)
                dfs2(e[i].to,e[i].to);
        }
    }
    
    int lca(int x,int y)
    {
        while(bl[x]!=bl[y])
        {
            if(deep[bl[x]]<deep[bl[y]]) swap(x,y);
            x = fa[bl[x]];
        }
        if(deep[x]>deep[y]) swap(x,y);
        return x;
    }
    
    void updown(int cur)
    {
        mx[cur]=max(mx[cur<<1],mx[cur<<1|1]);
    }
    
    void pushdown(int cur)
    {
        if(tag[cur])
        {
            tag[cur<<1]+=tag[cur];
            tag[cur<<1|1]+=tag[cur];
            mx[cur<<1]+=tag[cur];
            mx[cur<<1|1]+=tag[cur];
            tag[cur]=0;
        }
    }
    void modify(int l,int r,int cur,int L,int R,int z)
    {
        if(l>=L && r<=R)
        {
            tag[cur]+=z;
            mx[cur]+=z;
            return ;
        }
        if(l>R || r<L) return ;
        int mid=l+r>>1;
        pushdown(cur);
        modify(l,mid,cur<<1,L,R,z);
        modify(mid+1,r,cur<<1|1,L,R,z);
        updown(cur);
    }
    int query(int l,int r,int cur,int L,int R)
    {
        if(l>=L && r<=R) return mx[cur];
        if(l>R || r<L) return -inf;
        int mid=l+r>>1;
        pushdown(cur);
        int ans;
        ans=max(query(l,mid,cur<<1,L,R),query(mid+1,r,cur<<1|1,L,R));
        updown(cur);
        return ans;
    }
    void build(int l,int r,int cur)
    {
        if(l==r)
        {
            mx[cur]=deep[id[l]];
            return ;
        }
        int mid=l+r>>1;
        build(l,mid,cur<<1);
        build(mid+1,r,cur<<1|1);
        updown(cur);
    }
    struct LCT
    {
        int fa[mn],c[mn][2];
        bool nroot(int x)
        {
            return c[fa[x]][0]==x || c[fa[x]][1] ==x;
        }
        void rotate(int x)
        {
            int y=fa[x],z=fa[y];
            int flag;
            if(c[y][0]==x) flag=1;
            else flag=0;
            if(nroot(y))
            {
                if(c[z][0]==y) c[z][0]=x;
                else c[z][1]=x;
            }
            c[y][flag^1]=c[x][flag];fa[c[y][flag^1]]=y;
            c[x][flag]=y;
            fa[y]=x,fa[x]=z;
        }
        void splay(int x)
        {
            while(nroot(x))
            {
                int y=fa[x],z=fa[y];
                if(nroot(y))
                {
                    if((c[z][0]==y) ^ (c[y][0]==x)) rotate(x);
                    rotate(y);
                }
                rotate(x);
            }
        }
        int findroot(int x)
        {
            while(c[x][0]) {
                x=c[x][0];
            }
    
            return x;
        }
        void access(int x)
        {
            int y=0;
            while(x)
            {
                splay(x);
                if(c[x][1])
                {
                    int tmp=findroot(c[x][1]);
                    modify(1,n,1,in[tmp],out[tmp],1);
                }
                if(y)
                {
                    int tmp=findroot(y);
                    modify(1,n,1,in[tmp],out[tmp],-1);
                }
                c[x][1]=y;
                y=x;
                x=fa[x];
            }
        }
    }T;
    
    int main()
    {
        int opt,x,y,m;
        scanf("%d%d",&n,&m);
        for(int i=1; i<n; i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y),add(y,x);
        }
        deep[1]=1;
        dfs(1);
        dfs2(1,1);
        build(1,n,1);
        for(int i=1;i<=n;i++)
            T.fa[i]=fa[i];
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d",&opt,&x);
            if(opt==1)
                T.access(x);
            else if(opt==2)
            {
                scanf("%d",&y);
                int ans=0;
                ans=query(1,n,1,in[x],in[x]);
                ans+=query(1,n,1,in[y],in[y]);
                int z=lca(x,y);
                ans-=2*query(1,n,1,in[z],in[z]);
                ans++;
                printf("%d
    ",ans);
            }
            else  printf("%d
    ",query(1,n,1,in[x],out[x]));
        }
        return 0;
    }
  • 相关阅读:
    面板评分太低会算两次
    没有使用大漩涡传送门没有杀死大法师瓦格斯
    win10创建本地用户
    延迟着色
    GPU 优化总结
    UE4 减少APK包的大小
    UE4 性能优化方法(工具篇)
    Unreal Engine 4的常见Tips
    虚幻引擎4设置Visual Studio
    模型导入的单位问题
  • 原文地址:https://www.cnblogs.com/logeadd/p/9763158.html
Copyright © 2011-2022 走看看