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\n",ans);
        }
    }
}

 

 

posted @ 2018-02-04 16:52  fcwww  阅读(173)  评论(0编辑  收藏  举报