zoukankan      html  css  js  c++  java
  • SDOI2017 树点涂色

    题目描述

    题解:

    SDOI SD题

    LCT维护线段树,

    线段树维护dfs序。

    由于每次修改只是从根到x,我们可以将它理解为LCT的access操作。

    然后轻重链信息发生变化时,在线段树上改一下就好了。

    LCTaccess板子敲错导致自己做自己爷爷。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,m,hed[N],cnt;
    struct EG
    {
        int to,nxt;
    }e[2*N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    int pla[N],dep[N];
    struct segtree
    {
        int mx[N<<2],tag[N<<2];
        void update(int u)
        {
            mx[u] = max(mx[u<<1],mx[u<<1|1]);
        }
        void add(int u,int d)
        {
            tag[u]+=d;
            mx[u]+=d;
        }
        void pushdown(int u)
        {
            if(tag[u])
            {
                add(u<<1,tag[u]);
                add(u<<1|1,tag[u]);
                tag[u] = 0;
            }
        }
        void build(int l,int r,int u)
        {
            if(l==r)
            {
                mx[u] = dep[pla[l]];
                return ;
            }
            int mid = (l+r)>>1;
            build(l,mid,u<<1);
            build(mid+1,r,u<<1|1);
            update(u);
        }
        void insert(int l,int r,int u,int ql,int qr,int d)
        {
            if(l==ql&&r==qr)
            {
                add(u,d);
                return ;
            }
            pushdown(u);
            int mid = (l+r)>>1;
            if(qr<=mid)insert(l,mid,u<<1,ql,qr,d);
            else if(ql>mid)insert(mid+1,r,u<<1|1,ql,qr,d);
            else insert(l,mid,u<<1,ql,mid,d),insert(mid+1,r,u<<1|1,mid+1,qr,d);
            update(u);
        }
        int query(int l,int r,int u,int ql,int qr)
        {
            if(l==ql&&r==qr)return mx[u];
            pushdown(u);
            int mid = (l+r)>>1;
            if(qr<=mid)return query(l,mid,u<<1,ql,qr);
            else if(ql>mid)return query(mid+1,r,u<<1|1,ql,qr);
            else return max(query(l,mid,u<<1,ql,mid),query(mid+1,r,u<<1|1,mid+1,qr));
        }
        int ask(int l,int r,int u,int qx)
        {
            if(l==r)return mx[u];
            pushdown(u);
            int mid = (l+r)>>1;
            if(qx<=mid)return ask(l,mid,u<<1,qx);
            else return ask(mid+1,r,u<<1|1,qx);
        }
    }tr1;
    int tin[N],tout[N],tim;
    struct LCT
    {
        int fa[N],ch[N][2];
        bool rt[N];
        void rotate(int x)
        {
            int y = fa[x],z = fa[y],k = (ch[y][1]==x);
            if(rt[y])rt[x]=1,rt[y]=0;
            else ch[z][ch[z][1]==y]=x;
            fa[x] = z;
            ch[y][k] = ch[x][!k],fa[ch[x][!k]] = y;
            ch[x][!k] = y,fa[y] = x;
        }
        void splay(int x)
        {
            while(!rt[x])
            {
                int y = fa[x],z = fa[y];
                if(!rt[y])
                    (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
                rotate(x);
            }
        }
        int findroot(int x)
        {
            while(ch[x][0])x=ch[x][0];
            return x;
        }
        void access(int x)
        {
            int y = 0,v;
            while(x)
            {
                splay(x);
                if(ch[x][1])
                {
                    v = findroot(ch[x][1]);
                    tr1.insert(1,n,1,tin[v],tout[v],1);
                }
                if(y)
                {
                    v = findroot(y);
                    tr1.insert(1,n,1,tin[v],tout[v],-1);
                }
                rt[y]=0,rt[ch[x][1]]=1;
                ch[x][1] = y;
                y=x,x=fa[x];
            }
        }
    }tr2;
    int ff[N],son[N],siz[N],top[N];
    void dfs1(int u,int f)
    {
        siz[u]=1;
        ff[u]=f;
        tr2.fa[u]=f;
        tr2.rt[u]=1;
        dep[u]=dep[f]+1;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==f)continue;
            dfs1(to,u);
            siz[u]+=siz[to];
            if(siz[to]>siz[son[u]])son[u]=to;
        }
    }
    void dfs2(int u,int tp)
    {
        top[u] = tp;
        tin[u] = ++tim;pla[tim] = u;
        if(son[u])
        {
            dfs2(son[u],tp);
            for(int j=hed[u];j;j=e[j].nxt)
            {
                int to = e[j].to;
                if(to==ff[u]||to==son[u])continue;
                dfs2(to,to);
            }
        }
        tout[u]=tim;
    }
    int get_lca(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            x = ff[top[x]];
        }
        return dep[x]<dep[y]?x:y;
    }
    int main()
    {
    //    freopen("1.in","r",stdin);
        n = rd(),m = rd();
        for(int f,t,i=1;i<n;i++)
        {
            f=rd(),t=rd();
            ae(f,t),ae(t,f);
        }
        dfs1(1,0);
        dfs2(1,1);
        tr1.build(1,n,1);
        for(int opt,x,y,i=1;i<=m;i++)
        {
            opt = rd(),x = rd();
            if(opt==1)
            {
                tr2.access(x);
            }else if(opt==2)
            {
                y = rd();
                int k1 = tr1.ask(1,n,1,tin[x]);
                int k2 = tr1.ask(1,n,1,tin[y]);
                int lca = get_lca(x,y);
                int k3 = tr1.ask(1,n,1,tin[lca]);
                printf("%d
    ",k1+k2-2*k3+1);
            }else
            {
                printf("%d
    ",tr1.query(1,n,1,tin[x],tout[x]));
            }
        }
        return 0;
    }
  • 相关阅读:
    Windows多线程编程入门
    多字节字符与宽字符
    Linux静态库与动态库详解
    Linux下清理内存和Cache方法
    数据库设计范式
    mybatis面试问题
    Gson使用
    Linux 定时任务crontab使用
    Java-GC机制
    java内存模型
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10164059.html
Copyright © 2011-2022 走看看