zoukankan      html  css  js  c++  java
  • BZOJ 4817: [Sdoi2017]树点涂色

    4817: [Sdoi2017]树点涂色

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 273  Solved: 164
    [Submit][Status][Discuss]

    Description

    Bob有一棵n个点的有根树,其中1号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。定义一条路
    径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。Bob可能会进行这几种操作:
    1 x:
    把点x到根节点的路径上所有的点染上一种没有用过的新颜色。
    2 x y:
    求x到y的路径的权值。
    3 x y:
    在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。
    Bob一共会进行m次操作
     

    Input

    第一行两个数n,m。
    接下来n-1行,每行两个数a,b,表示a与b之间有一条边。
    接下来m行,表示操作,格式见题目描述
    1<=n,m<=100000
     

    Output

    每当出现2,3操作,输出一行。
    如果是2操作,输出一个数表示路径的权值
    如果是3操作,输出一个数表示权值的最大值
     

    Sample Input

    5 6
    1 2
    2 3
    3 4
    3 5
    2 4 5
    3 3
    1 4
    2 4 5
    1 5
    2 4 5

    Sample Output

    3
    4
    2
    2
     
    感觉自己的破题能力是不是药丸啊,这么显然的LCT都没看出来……
    如果我们像lct那样操作,一条路径上不同颜色数就是lct中虚边的数量+1。
    那么每次多出来或者减少一条虚边的时候就修改子树权值就好了,这里可以先求出dfs序然后线段树维护。
    一个细节:在splay上连边的时候,删掉的虚边并不是被作为右儿子那棵solay的根对应节点所在子树,而是这棵splay的最左一个节点。
    #include<cstdio>
    #include<algorithm>
    #define MN 410001
    #define lp (p<<1)
    #define rp ((p<<1)|1)
    using namespace std;
    
    int read_p,read_ca;
    inline int read(){
        read_p=0;read_ca=getchar();
        while(read_ca<'0'||read_ca>'9') read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p;
    }
    struct na{int y,ne;}b[MN<<1];
    int n,m,o,l[MN],num=0,x,y,fa[MN],ch[MN][2],df[MN],lo[MN],nm=0,v[MN],de[MN],ma[MN],s[MN],pdf[MN],f[MN][20];
    bool rt[MN];
    inline int max(int a,int b){return a>b?a:b;}
    inline void in(int x,int y){b[++num].y=y;b[num].ne=l[x];l[x]=num;}
    
    void rot(int k){
        int p=fa[k],bo=ch[p][1]==k;
        ch[p][bo]=ch[k][!bo];
        ch[k][!bo]=p;
        fa[ch[p][bo]]=p;
        fa[k]=fa[p];
        fa[p]=k;
        if (rt[p]) rt[p]=0,rt[k]=1;else ch[fa[k]][ch[fa[k]][1]==p]=k;
        p=k;
    }
    
    void splay(int x){
        while (!rt[x]){
            if (rt[fa[x]]) rot(x);else
            if ((ch[fa[fa[x]]][1]==fa[x])==(ch[fa[x]][1]==x)) rot(fa[x]),rot(x);else rot(x),rot(x);
        }
    }
    
    void add(int p,int l,int r,int L,int R,int v){
        if (l==L&&r==R) s[p]+=v,ma[p]+=v;else{
            int mid=l+r>>1;
            if (R<=mid) add(lp,l,mid,L,R,v);else
            if (L>mid) add(rp,mid+1,r,L,R,v);else
            add(lp,l,mid,L,mid,v),add(rp,mid+1,r,mid+1,R,v);
            ma[p]=max(ma[lp],ma[rp])+s[p];
        }
    }
    
    int ask(int p,int l,int r,int k){
        if (l==r) return ma[p];
        int mid=l+r>>1;
        if (k<=mid) return ask(lp,l,mid,k)+s[p];else return ask(rp,mid+1,r,k)+s[p];
    }
    
    int ask(int p,int l,int r,int L,int R){
        if (L==l&&R==r) return ma[p];
        int mid=l+r>>1;
        if (R<=mid) return ask(lp,l,mid,L,R)+s[p];else
        if (L>mid) return ask(rp,mid+1,r,L,R)+s[p];else
        return max(ask(lp,l,mid,L,mid),ask(rp,mid+1,r,mid+1,R))+s[p];
    }
    
    int lf(int x){return ch[x][0]?lf(ch[x][0]):x;}
    
    void acc(int x){
        for (int i=0;x;x=fa[i=x]){
            splay(x);
            if (ch[x][1]) add(1,1,nm,df[lf(ch[x][1])],lo[lf(ch[x][1])],1),rt[ch[x][1]]=1;
            rt[ch[x][1]=i]=0;if (ch[x][1]) add(1,1,nm,df[lf(ch[x][1])],lo[lf(ch[x][1])],-1);
        }
    }
    
    void dfs(int x){
        f[x][0]=fa[x];
        for (int i=1;i<20;i++) f[x][i]=f[f[x][i-1]][i-1];
        df[x]=++nm;rt[x]=1;de[x]=de[fa[x]]+1;pdf[nm]=de[x];
        for (int i=l[x];i;i=b[i].ne)
        if (b[i].y!=fa[x]) fa[b[i].y]=x,dfs(b[i].y);
        lo[x]=nm;
    }
    
    void build(int p,int l,int r){
        if (l==r) {ma[p]=pdf[l];return;}
        int mid=l+r>>1;
        build(lp,l,mid);build(rp,mid+1,r);
        ma[p]=max(ma[lp],ma[rp]);
    }
    
    int lca(int x,int y){
        if (de[x]<de[y]) swap(x,y);
        for (int i=19;i>=0;i--)
        if (f[x][i]&&de[f[x][i]]>=de[y]) x=f[x][i];
        if (x==y) return x;
        for (int i=19;i>=0;i--)
        if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    
    int main(){
        register int i;
        n=read();m=read();
        for (i=1;i<n;i++) x=read(),y=read(),in(x,y),in(y,x);
        dfs(1);
        build(1,1,n);
        while (m--){
            o=read();
            if (o==1) acc(read());else
            if (o==2) x=read(),y=read(),o=lca(x,y),printf("%d
    ",ask(1,1,n,df[x])+ask(1,1,n,df[y])-2*ask(1,1,n,df[o])+1);else
            x=read(),printf("%d
    ",ask(1,1,n,df[x],lo[x]));
        }
    }
    View Code
  • 相关阅读:
    一分钟制作U盘版BT3
    微软历史最高市值是多少?
    Windows 7系统安装MySQL5.5.21图解
    cocos2d-x3.0 Physics新的物理引擎
    java使用javamail读取邮箱(收件箱为例)
    Java实现第九届蓝桥杯字母阵列
    Java实现第九届蓝桥杯字母阵列
    Java实现第九届蓝桥杯字母阵列
    Java实现第九届蓝桥杯猴子分香蕉
    Java实现第九届蓝桥杯猴子分香蕉
  • 原文地址:https://www.cnblogs.com/Enceladus/p/6713473.html
Copyright © 2011-2022 走看看