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

    题目链接

    发现1操作很像lct中的access,然后它每次染的又是一个新颜色,因此同一个颜色就在同一颗splay里了,且一个点到根的权值val[i]也就是到根路径上虚边的个数,然后看access时会对哪些点的val[i]产生影响。

    以下的原儿子表示原来与x在同一颗splay中的儿子 (注意不是splay中x的儿子,是原树中x的儿子,即splay中x的后继)。

    当x断开与它原儿子所在splay的连接时,原儿子的子树val都要+1,接上的新儿子的splay,新儿子所在子树val要-1。

    对于2操作,相当于统计x~y路径上虚边个数+1,val[x]+val[y]-2*val[lca]+1即是。

    对于3操作在子树中找个最大的val即可。

    val的话可以用线段树维护。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<stack>
    #include<map>
    #define P puts("lala")
    #define cp cerr<<"lala"<<endl
    #define ln putchar('
    ')
    #define sp putchar(' ')
    #define pb push_back
    #define fi first
    #define se second 
    #define mkp make_pair
    using namespace std;
    typedef pair<int,int> pii;
    inline void read(int &re)
    {
        char ch=getchar();int g=1;
        while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
        re=0;
        while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
        re*=g;
    }
    typedef long long ll;
    inline void read(ll &re)
    {
        char ch=getchar();ll g=1;
        while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
        re=0;
        while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+ch-48ll,ch=getchar();
        re*=g;
    }
    
    const int N=100050;
    int maxv[N<<2],add[N<<2],fa[N],ch[N][2];
    int siz[N],dfn[N],tot=0,is[N],f[N][21],n,dep[N];
    
    int head[N],cnt=0;
    struct node
    {
        int to,next;
    }e[N<<1];
    inline void add_edge(int x,int y)
    {
        e[++cnt]=(node){y,head[x]};head[x]=cnt;
        e[++cnt]=(node){x,head[y]};head[y]=cnt;
    }
    
    void build(int o,int l,int r)
    {
        if(l==r) {maxv[o]=dep[is[l]];return ;}
        int mid=l+r>>1;
        build(o<<1,l,mid); build(o<<1|1,mid+1,r);
        maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
    }
    void pushdown(int o)
    {
        if(add[o])
        {
            add[o<<1]+=add[o]; add[o<<1|1]+=add[o];
            maxv[o<<1]+=add[o]; maxv[o<<1|1]+=add[o];
            add[o]=0;
        }
    }
    void update(int o,int l,int r,int x,int y,int k) //add k
    {
        if(x<=l&&r<=y) {add[o]+=k;maxv[o]+=k;return ;}
        pushdown(o);
        int mid=l+r>>1;
        if(x<=mid) update(o<<1,l,mid,x,y,k);
        if(y>mid) update(o<<1|1,mid+1,r,x,y,k);
        maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
    }
    int query(int o,int l,int r,int x,int y)
    {
        if(x<=l&&r<=y) return maxv[o];
        pushdown(o);
        int mid=l+r>>1,ans=0;
        if(x<=mid) ans=query(o<<1,l,mid,x,y);
        if(y>mid) ans=max(ans,query(o<<1|1,mid+1,r,x,y));
        return ans;
    }
    
    inline bool ge(int x) {return ch[fa[x]][1]==x;}
    inline bool isroot(int x) {return ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x;}
    inline void rotate(int x)
    {
        int f=fa[x],g=fa[f],wh=ge(x);
        if(!isroot(f)) ch[g][ch[g][1]==f]=x;
        ch[f][wh]=ch[x][wh^1]; fa[ch[f][wh]]=f;
        ch[x][wh^1]=f; fa[f]=x;
        fa[x]=g;
    }
    void splay(int x)
    {
        for(int f;(f=fa[x])&&!isroot(x);rotate(x))
            if(!isroot(f)) rotate(ge(x)==ge(f)?f:x);
    }
    
    int nex(int x)
    {
        x=ch[x][1];
        while(ch[x][0]) x=ch[x][0];
        return x;
    }
    
    void access(int x)
    {
        for(int t=0;x;t=x,x=fa[x])
        {
            splay(x);
            if(ch[x][1]) 
            {
                int y=nex(x);
                update(1,1,n,dfn[y],dfn[y]+siz[y]-1,1);
            }
            ch[x][1]=t;
            if(ch[x][1]) 
            {
                int y=nex(x);
                update(1,1,n,dfn[y],dfn[y]+siz[y]-1,-1);
            }
        }
    }
    
    void dfs(int u,int dad,int d)
    {
        fa[u]=dad; f[u][0]=dad;
        dfn[u]=++tot; is[tot]=u;
        siz[u]=1; dep[u]=d;
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v==dad) continue;
            dfs(v,u,d+1);
            siz[u]+=siz[v];
        }
    }
    
    int lca(int x,int y)
    {
        if(dep[x]<dep[y]) swap(x,y);
        int d=dep[x]-dep[y];
        for(int i=19;i>=0;--i) if(d&(1<<i)) 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 ask(int x,int y)
    {
        int o=lca(x,y);
        return query(1,1,n,dfn[x],dfn[x])+query(1,1,n,dfn[y],dfn[y])
        -query(1,1,n,dfn[o],dfn[o])*2;
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);freopen("1.out","w",stdout);
    #endif
        int i,j,opt,T;
        read(n);read(T);
        for(i=1;i<n;++i)
        {
            int x,y;read(x);read(y);
            add_edge(x,y);
        }
    
        dfs(1,0,0);
        for(j=1;j<=19;++j) for(i=1;i<=n;++i) f[i][j]=f[f[i][j-1]][j-1];
    
        build(1,1,n);
        for(int cas=1;cas<=T;++cas)
        {
            read(opt);
            if(opt==1)
            {
                int x;read(x);
                access(x);
            }
            else if(opt==2) 
            {
                int x,y;read(x);read(y);
                printf("%d
    ",ask(x,y)+1);
            }
            else 
            {
                int x;read(x);
                printf("%d
    ",query(1,1,n,dfn[x],dfn[x]+siz[x]-1)+1);
            }
        }
        return 0;
    }
    /*
    
    */
  • 相关阅读:
    POJ 2251 Dungeon Master
    HDU 3085 Nightmare Ⅱ
    CodeForces 1060 B Maximum Sum of Digits
    HDU 1166 敌兵布阵(树状数组)
    HDOJ 2050 折线分割平面
    HDU 5879 Cure
    HDU 1878 欧拉回路
    HDU 6225 Little Boxes
    ZOJ 2971 Give Me the Number
    HDU 2680 Choose the best route
  • 原文地址:https://www.cnblogs.com/thkkk/p/7868468.html
Copyright © 2011-2022 走看看