zoukankan      html  css  js  c++  java
  • B20J_2243_[SDOI2011]染色_树链剖分+线段树

    B20J_2243_[SDOI2011]染色_树链剖分+线段树

    一下午净调这题了,争取晚上多做几道。

    题意:

    给定一棵有n个节点的无根树和m个操作,操作有2类:
    1、将节点a到节点b路径上所有点都染成颜色c;
    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
    如“112221”由3段组成:“11”、“222”和“1”。
     
    分析:
    线段树结点维护信息:区间内颜色段数t ,区间左端点颜色lco,区间右端点颜色rco,延迟标记lazy。
    上传时lco[pos]=lco[lson];rco[pos]=rco[rson];t[pos]=t[lson]+t[rson];如果左区间右端点和右区间左端点颜色相同,区间段数减一;
    查询时先加上区间对应的颜色段数(线段树区间合并),然后每次找到上下端点的颜色(直接单点查找),这个跳链的时候就能找到,如果UC=DC,ans--;
    注意每次标记下传的时机。
     
    代码
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 1000010
    #define M 2062145
    #define lson pos<<1
    #define rson pos<<1|1
    int head[N],to[N<<1],nxt[N<<1],co[N],cnt,n,m,scc;
    char ch[10];
    int dep[N],fa[N],siz[N],son[N],top[N];
    int t[M],lzy[M],idx[N],lco[M],rco[M],a[N];
    inline void read(int &x)
    {
        int f=1;x=0;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
        x*=f;    
    }
    inline void add(int u,int v)
    {
        to[++cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt;    
    }
    inline void dfs1(int x,int y)
    {
        dep[x]=dep[y]+1;
        fa[x]=y;
        siz[x]=1;
        for(int i=head[x];i;i=nxt[i])
        {
            if(to[i]!=y)
            {
                dfs1(to[i],x);
                siz[x]+=siz[to[i]];
                if(siz[to[i]]>siz[son[x]])
                {
                    son[x]=to[i];
                }
            }
        }
    }
    inline void dfs2(int x,int t)
    {
        top[x]=t;
        idx[x]=++scc;
        if(son[x])dfs2(son[x],t);
        for(int i=head[x];i;i=nxt[i])
        {
            if(to[i]!=fa[x]&&to[i]!=son[x])
            {
                dfs2(to[i],to[i]);
            }
        }
    }
    inline void pud(int pos)
    {
        if(!lzy[pos])return ;
        t[lson]=1;lzy[lson]=lco[lson]=rco[lson]=lzy[pos];    
        t[rson]=1;lzy[rson]=lco[rson]=rco[rson]=lzy[pos];
        lzy[pos]=0;    
    }
    inline void up(int l,int r,int pos,int x,int y,int c)
    {
        if(x<=l&&y>=r)
        {
            t[pos]=1;
            lco[pos]=c;
            rco[pos]=c;
            lzy[pos]=c;
            return ;
        }
        pud(pos);
        int mid=l+r>>1;
        if(x<=mid)up(l,mid,lson,x,y,c);
        if(y>mid)up(mid+1,r,rson,x,y,c);
        t[pos]=t[lson]+t[rson];
        if(lco[rson]==rco[lson])t[pos]--;
        lco[pos]=lco[lson];
        rco[pos]=rco[rson];    
    }
    inline int query(int l,int r,int pos,int x,int y)
    {
        pud(pos);
        int re=0;
        int mid=l+r>>1;
        if(x<=l&&y>=r)
        {
            return t[pos];
        }
        if(y<=mid) return query(l,mid,lson,x,y);
        else if(x>mid) return query(mid+1,r,rson,x,y);
        else 
        {
            re=query(l,mid,lson,x,y)+query(mid+1,r,rson,x,y);
            if(lco[rson]==rco[lson])re--;
            return re;    
        }
    }
    inline int col(int l,int r,int x,int pos)
    {
        pud(pos);
        if(l==r)return     lco[pos];
        int mid=l+r>>1;
        if(x<=mid)return col(l,mid,x,lson);
        else return col(mid+1,r,x,rson);
    }
    int main()
    {
        read(n),read(m);
        int x,y,z;
        register int i;
        for(i=1;i<=n;++i)
        {
            read(a[i]);
        }
        for(i=1;i<n;++i)
        {
            read(x),read(y);
            add(x,y);
            add(y,x);
        }
        dfs1(1,0);
        dfs2(1,1);
        for(i=1;i<=n;++i)up(1,n,1,idx[i],idx[i],a[i]);
        while(m--)
        {
            scanf("%s",ch);
            if(ch[0]=='C')
            {
                read(x),read(y),read(z);
                while(top[x]!=top[y])
                {
                    if(dep[top[x]]>dep[top[y]])swap(x,y);
                    up(1,n,1,idx[top[y]],idx[y],z);
                    y=fa[top[y]];
                }
                if(dep[x]<dep[y])swap(x,y);
                up(1,n,1,idx[y],idx[x],z);
            }
            else 
            {
                read(x),read(y);
                int ans=0;
                while(top[x]!=top[y])
                {
                    if(dep[top[x]]>dep[top[y]])swap(x,y);
                    int DC=col(1,n,idx[top[y]],1),UC=col(1,n,idx[fa[top[y]]],1);
                    ans+=query(1,n,1,idx[top[y]],idx[y]);
                    if(UC==DC)ans--;    
                    y=fa[top[y]];
                }
                if(dep[x]<dep[y])swap(x,y);
                ans+=query(1,n,1,idx[y],idx[x]);
                if(!ans)ans=1;
                printf("%d
    ",ans);
            }
        }
    }
    
  • 相关阅读:
    前端响应式开发
    前端兼容性问题解决方案(二)
    web storage
    flex布局 滚动条失效
    ant-design-vue form表单 defaultValue默认值
    node express 中间件 http-proxy-middleware 和 express-http-proxy 转发 搞定 post 超时
    Math.min & Math.max & apply
    Backbone源码分析-noConflict
    安卓下浏览器(包括微信)video 小窗口播放
    前端工作流
  • 原文地址:https://www.cnblogs.com/suika/p/8413562.html
Copyright © 2011-2022 走看看