zoukankan      html  css  js  c++  java
  • [bzoj4817][Sdoi2017]树点涂色

    来自FallDream的博客,未经允许,请勿转载,谢谢。

    Bob有一棵n个点的有根树,其中1号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。定义一条路
    径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。Bob可能会进行这几种操作:
    1 x:把点x到根节点的路径上所有的点染上一种没有用过的新颜色。
    2 x y:求x到y的路径的权值。
    3 x:在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。
    Bob一共会进行m次操作
    n,m<=100000
     
    发现这道题的操作很像linkcuttree嗯? 1操作其实就是access一个点,然后2操作我们可以从两个点暴力跳,统计经过了几条虚边,再减去lca处的就行了;3操作我们发现每次access把两段接起来的时候下面那个子树答案-1,上面这个点的后继(如果有)的子树答案+1,这个可以求dfs序之后用一个权值线段树求最大值维护,所以这道题就做完了。复杂度$O(nlog^{2}n)$
    #include<cstdio>
    #include<iostream>
    #define R register
    #define MN 100000
    #define MD 16
    #define getchar() (*S++)
    char B[1<<26],*S=B; 
    using namespace std;
    inline int read()
    {
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x;
    }
    int f[MD+1][MN+5];
    int n,m,head[MN+5],cnt=0,nl[MN+5],nr[MN+5],dn=0,fa[MN+5],c[MN+5][2],dep[MN+5],L[MN+5],p[MN+5];
    bool rev[MN+5];
    struct Tree{int l,r,x,val;}T[MN*4+5];
    struct edge{int to,next;}e[MN*2+5];
    inline bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
    inline void update(int x){L[x]=c[x][0]?L[c[x][0]]:x;}
    inline void ins(int f,int t)
    {
        e[++cnt]=(edge){t,head[f]};head[f]=cnt;
        e[++cnt]=(edge){f,head[t]};head[t]=cnt;
    }
    
    inline void pushdown(int x)
    {
        int l=x<<1,r=x<<1|1;
        T[l].x+=T[x].val;T[l].val+=T[x].val;
        T[r].x+=T[x].val;T[r].val+=T[x].val;
        T[x].val=0;
    }
    
    void build(int x,int l,int r)
    {
        if((T[x].l=l)==(T[x].r=r)) {T[x].x=dep[p[l]]+1;return;}
        int mid=l+r>>1;
        build(x<<1,l,mid);build(x<<1|1,mid+1,r);
        T[x].x=max(T[x<<1].x,T[x<<1|1].x);
    }
    
    void renew(int x,int l,int r,int ad)
    {
        if(T[x].l==l&&T[x].r==r)
        {
            T[x].x+=ad;T[x].val+=ad;
            return;
        }
        if(T[x].val)pushdown(x);
        int mid=T[x].l+T[x].r>>1;
        if(r<=mid) renew(x<<1,l,r,ad);
        else if(l>mid) renew(x<<1|1,l,r,ad);
        else renew(x<<1,l,mid,ad),renew(x<<1|1,mid+1,r,ad);
        T[x].x=max(T[x<<1].x,T[x<<1|1].x);
    }
    
    int query(int x,int l,int r)
    {
        if(T[x].l==l&&T[x].r==r)return T[x].x;
        if(T[x].val) pushdown(x);
        int mid=T[x].l+T[x].r>>1;
        if(r<=mid) return query(x<<1,l,r);
        else if(l>mid) return query(x<<1|1,l,r);
        else return max(query(x<<1,l,mid),query(x<<1|1,mid+1,r));
    }
    
    void dfs(int x,int fat)
    {
        p[nl[x]=++dn]=x;f[0][x]=fa[x]=fat;
        for(int i=head[x];i;i=e[i].next)
            if(e[i].to!=fat) dep[e[i].to]=dep[x]+1,dfs(e[i].to,x);
        nr[x]=dn;
    }
    
    void rotate(int x)
    {
        int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
        if(!isroot(y))c[z][c[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        update(y);update(x);
    }
    
    void splay(int x)
    {
        for(;!isroot(x);rotate(x))
            if(!isroot(fa[x]))rotate((c[fa[fa[x]]][1]==fa[x]^c[fa[x]][1]==x)?x:fa[x]);
    }
    
    void access(int x)
    {
        for(int y=0;x;x=fa[y=x])
        {
            splay(x);if(c[x][1])renew(1,nl[L[c[x][1]]],nr[L[c[x][1]]],1);
            c[x][1]=y;
            if(y)renew(1,nl[L[y]],nr[L[y]],-1);
        }
    }
    int lca(int x,int y)
    {
        if(dep[x]<dep[y])swap(x,y);
        for(int k=dep[x]-dep[y],j=0;k;k>>=1,++j)
            if(k&1) x=f[j][x];
        if(x==y)return x;
        for(int i=MD;i>=0;i--)
            if(f[i][x]!=f[i][y])
                x=f[i][x],y=f[i][y];
        return f[0][x];
    }
    
    inline int work(int x)
    {
        int sum=0;
        for(;x;x=fa[x],++sum)
            splay(x);
        return sum;
    }
    
    inline int solve(int x,int y)
    {
        int z=lca(x,y);
        return work(x)+work(y)-2*work(z)+1;
    }
    
    int main()
    {
        fread(B,1,1<<26,stdin);
        n=read();m=read();
        for(R int i=1;i<n;i++) ins(read(),read());
        dfs(1,0);build(1,1,n);
        for(R int i=1;i<=n;i++)L[i]=i;
        for(R int j=1;j<=MD;j++)
            for(R int i=1;i<=n;i++)
                f[j][i]=f[j-1][f[j-1][i]];
        for(R int i=1;i<=m;i++)
        {
            int op=read();
            if(op==1) access(read());
            else if(op==2) printf("%d
    ",solve(read(),read()));
            else {int x=read();printf("%d
    ",query(1,nl[x],nr[x]));}
        }
        return 0;
    }
  • 相关阅读:
    Java equals()和hashCode()重写总结
    常见ORM框架理解
    struts2的第一个小页面
    Java开发StringBuilder类
    “中软综合项目实训”——把学生当员工培养
    中软寻梦
    软件开发学习的5大技巧
    从学生心理入手
    IT技术人员的职业发展方向
    驱动创新 引领未来
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj4817.html
Copyright © 2011-2022 走看看