• bzoj千题计划275:bzoj4817: [Sdoi2017]树点涂色


    http://www.lydsy.com/JudgeOnline/problem.php?id=4817

    lct+线段树+dfs序

    操作1:access

    操作2:u到根的-v到根的-lca到根的*2+1

    操作3:查询线段树区间最大值

    1A,嘎嘎嘎

    #include<cmath>
    #include<cstdio>
    #include<iostream>
    
    using namespace std;
    
    #define max(x,y) ((x)>(y) ? (x) : (y))
    
    #define N 100001
    
    int n;
    int front[N],to[N<<1],nxt[N<<1],tot;
    
    int id[N],dy[N],lst[N],tim;
    int dep[N];
    
    int lim,F[N][17];
    
    int mx[N<<2],tag[N<<2];
    
    int root;
    int fa[N],ch[N][2];
    bool rev[N];
    
    int st[N],top;
    
    int ans;
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
    }
    
    void dfs(int x)
    {
        id[x]=++tim;
        dy[tim]=x;
        dep[x]=dep[fa[x]]+1;
        for(int i=front[x];i;i=nxt[i])
            if(to[i]!=fa[x])
            {
                F[to[i]][0]=fa[to[i]]=x;
                dfs(to[i]);
            }
        lst[x]=tim;
    }
    
    void build(int k,int l,int r)
    {
        if(l==r) 
        {
            mx[k]=dep[dy[l]];
            return;
        }
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        mx[k]=max(mx[k<<1],mx[k<<1|1]);
    }
    
    void down(int k)
    {
        mx[k<<1]+=tag[k];
        tag[k<<1]+=tag[k];
        mx[k<<1|1]+=tag[k];
        tag[k<<1|1]+=tag[k];
        tag[k]=0;
    }
    
    void change(int k,int l,int r,int opl,int opr,int w)
    {
        if(l>=opl && r<=opr)
        {
            mx[k]+=w;
            tag[k]+=w;
            return;
        }
        if(tag[k]) down(k);
        int mid=l+r>>1;
        if(opl<=mid) change(k<<1,l,mid,opl,opr,w);
        if(opr>mid) change(k<<1|1,mid+1,r,opl,opr,w);
        mx[k]=max(mx[k<<1],mx[k<<1|1]);
    }
    
    void Change(int x,int w)
    {
        if(x==root) change(1,1,n,1,n,w);
        else if(id[x]>id[root] && id[x]<=lst[root]) change(1,1,n,id[x],lst[x],w);
        else
        {
            int t=root,c=dep[root]-dep[x]-1;
            for(int i=lim;i>=0;--i)
                if(c&(1<<i)) t=F[t][i];
            if(id[t]>1) change(1,1,n,1,id[t]-1,w);
            if(lst[t]<n) change(1,1,n,lst[t]+1,n,w);
        }
    }
    
    int query1(int k,int l,int r,int pos)
    {
        if(l==r) return mx[k];
        if(tag[k]) down(k);
        int mid=l+r>>1;
        if(pos<=mid) return query1(k<<1,l,mid,pos);
        return query1(k<<1|1,mid+1,r,pos);
    }
    
    void query2(int k,int l,int r,int opl,int opr)
    {
        if(l>=opl && r<=opr)
        {
            ans=max(ans,mx[k]);
            return;
        }
        if(tag[k]) down(k);
        int mid=l+r>>1;
        if(opl<=mid) query2(k<<1,l,mid,opl,opr);
        if(opr>mid) query2(k<<1|1,mid+1,r,opl,opr);
    }
    
    void push_down(int x)
    {
        if(rev[x])
        {
            if(ch[x][0]) rev[ch[x][0]]^=1;
            if(ch[x][1]) rev[ch[x][1]]^=1;
            rev[x]^=1;
        }
    }
    
    bool is_root(int x)
    {
        return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
    }
    
    bool get_son(int x)
    {
        return ch[fa[x]][1]==x;
    }
        
    void rotate(int x)
    {
        int y=fa[x],z=fa[y];
        bool k=ch[y][1]==x;
        if(!is_root(y)) ch[z][ch[z][1]==y]=x;
        ch[y][k]=ch[x][k^1]; ch[x][k^1]=y;
        fa[x]=z; fa[y]=x; fa[ch[y][k]]=y;
    }
    
    void splay(int x)
    {
        st[top=1]=x;
        for(int i=x;!is_root(i);i=fa[i]) st[++top]=fa[i];
        for(int i=top;i;--i) push_down(st[i]);
        int y;
        while(!is_root(x))
        {
            y=fa[x];
            if(!is_root(y)) rotate(get_son(x)==get_son(y) ? x : y );
            rotate(x);
        }
    }
    
    int find_root(int x)
    {
        push_down(x);
        while(ch[x][0])
        {
            x=ch[x][0];
            push_down(x);
        }
        return x;
    }
    
    void access(int x)
    {
        int t=0;
        while(x)
        {
            splay(x);
            if(ch[x][1]) Change(find_root(ch[x][1]),1);
            ch[x][1]=t;
            if(t) Change(find_root(t),-1);
            t=x; x=fa[x];
        }
    }
    
    int get_lca(int u,int v)
    {
        if(dep[u]<dep[v]) std::swap(u,v);
        int d=dep[u]-dep[v];
        for(int i=lim;i>=0;--i)
            if(d&(1<<i)) u=F[u][i];
        if(u==v) return u;
        for(int i=lim;i>=0;--i)
            if(F[u][i]!=F[v][i]) u=F[u][i],v=F[v][i];
        return F[u][0];
    }
    
    int main()
    {
        int m;
        read(n); read(m);
        lim=log(n)/log(2);
        int u,v;
        for(int i=1;i<n;++i)
        {
            read(u); read(v);
            add(u,v);
        }
        dfs(1);
        for(int j=1;j<=lim;++j)
            for(int i=1;i<=n;++i)
                F[i][j]=F[F[i][j-1]][j-1];
        build(1,1,n);
        root=1;
        int ty;
        int lca;
        while(m--)
        {
            read(ty); read(u);
            if(ty==1) access(u);
            else if(ty==2) 
            {
                read(v);
                lca=get_lca(u,v);
                printf("%d
    ",query1(1,1,n,id[u])+query1(1,1,n,id[v])-query1(1,1,n,id[lca])*2+1);
            }
            else 
            {
                ans=0;
                query2(1,1,n,id[u],lst[u]);
                printf("%d
    ",ans);
            }
        }
    }
  • 相关阅读:
    方法
    数组
    Scanner类+Random
    运算符2
    运算符1
    Linux中Oracle的安装
    redis安装常见错误
    redis常用命令
    Linux中redis安装
    修改Oracle字符集
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8551701.html
Copyright © 2020-2023  润新知