[SDOI2011]染色

◇◆丶佛笑我妖孽 提交于 2020-01-07 04:03:33

染色

给定一棵有n个节点的无根树和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c;

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),

如“112221”由3段组成:“11”、“222”和“1”。

请你写一个程序依次完成这m个操作。

Input

第一行包含2个整数n和m,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面n-1行每行包含两个整数x和y,表示x和y之间有一条无向边。

下面m行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

Output

对于每个询问操作,输出一行答案。

Sample Input

6 5

2 2 1 2 1 1

1 2

1 3

2 4

2 5

2 6

Q 3 5

C 2 1 1

Q 3 5

C 5 1 2

Q 3 5

Sample Output

3

1

2

思路:

树链剖分模板,存下一段中的左边界\(\And\)右边界\(\And\)出现段数

\(\mathfrak{Talk\ is\ cheap,show\ you\ the\ code.}\)

// #pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
# define read read1<int>()
# define Type template<typename T>
Type inline const T read1(){
    T m=0;
    char k=getchar();
    while(('0'>k||k>'9')&&(k!='-'))k=getchar();
    const bool f=(k=='-'?1:0);
    if(f)k=getchar();
    while('0'<=k&&k<='9')m=(m<<3)+(m<<1)+(k^48),k=getchar();
    return f?-m:m;
}
# define N 100001
int rk[N],dfn[N],f[N],son[N],siz[N],top[N],d[N],tot,va[N],s,b[N<<2];
class Tem{
    public:
        int lx,rx,h;
        Tem(int _=0,int __=0,int ___=0):lx(_),rx(__),h(___){};
        Tem& operator +=(Tem r){
            if(rx==r.lx)--h;
            rx=r.rx;h+=r.h;
            return *this;
        }
        Tem operator + (Tem r){return Tem(*this)+=r;}
        Tem operator ~ (){return Tem(rx,lx,h);}
}v[N<<2];
int Max(int a,int b){return a>b?a:b;}
struct E{int v,n;E(){}E(int a,int b):v(a),n(b){}}G[N<<1];
void add(int u,int v,int n){
    G[n]=E(v,b[u]);
    b[u]=n;
    G[--n]=E(u,b[v]);
    b[v]=n;
}
# define ls (d<<1)
# define rs (d<<1|1)
void pushup(int d){v[d]=v[ls]+v[rs];}
void build(int l,int r,int d){
    if(l==r)v[d].lx=v[d].rx=va[rk[l]],v[d].h=1;
    else{
        int mid=l+r>>1;
        build(l,mid,ls);build(mid+1,r,rs);
        pushup(d);
    }
}
Tem query(int l,int r,int tl,int tr,int d){
    if(l==tl&&tr==r)return v[d];
    int mid=tl+tr>>1;
    if(v[d].h==1)v[rs]=v[ls]=v[d];
    if(r<=mid)return query(l,r,tl,mid,d<<1);
    if(l>mid)return query(l,r,mid+1,tr,d<<1|1);
    return query(l,mid,tl,mid,d<<1)+query(mid+1,r,mid+1,tr,d<<1|1);
}
void cover(int l,int r,int v1,int d,int tl,int tr){
    if(l==tl&&r==tr)return (void)(v[d].lx=v[d].rx=v1,v[d].h=1);
    int mid=tl+tr>>1;
    if(v[d].h==1)v[rs]=v[ls]=v[d];
    if(r<=mid)cover(l,r,v1,ls,tl,mid);
    else if(l>mid)cover(l,r,v1,rs,mid+1,tr);
    else cover(l,mid,v1,ls,tl,mid),cover(mid+1,r,v1,rs,mid+1,tr);
    pushup(d);
}
void dfs1(int n,int fa){
    f[n]=fa;siz[n]=1;
    d[n]=d[fa]+1;son[n]=0;
    for(int i=b[n];i;i=G[i].n)
        if(G[i].v^fa){
            dfs1(G[i].v,n);
            siz[n]+=siz[G[i].v];
            if(siz[G[i].v]>siz[son[n]])
                son[n]=G[i].v;
        }
}
void dfs2(int n,int k){
    rk[dfn[n]=++tot]=n;
    top[n]=k;
    if(son[n])dfs2(son[n],k);
    for(int i=b[n];i;i=G[i].n)
        if(G[i].v^f[n]&&G[i].v^son[n])
            dfs2(G[i].v,G[i].v);
}
Tem inquiry(int u,int v){
    int tu=top[u],tv=top[v];
    Tem lans(0,0,0),rans(0,0,0);
    bool lfl=1,rfl=1;
    while(tu^tv)
        if(d[tu]>d[tv]){
            if(lfl)lans=~query(dfn[tu],dfn[u],1,s,1),lfl=0;
            else lans+=~query(dfn[tu],dfn[u],1,s,1);
            tu=top[u=f[tu]];
        }
        else{
            if(rfl)rans=query(dfn[tv],dfn[v],1,s,1),rfl=0;
            else rans=query(dfn[tv],dfn[v],1,s,1)+rans;
            tv=top[v=f[tv]];
        }
    if(d[u]>=d[v])
        if(rfl)rans=~query(dfn[v],dfn[u],1,s,1),rfl=0;
        else rans=~query(dfn[v],dfn[u],1,s,1)+rans;
    else if(lfl)lans=query(dfn[u],dfn[v],1,s,1),lfl=0;
        else lans+=query(dfn[u],dfn[v],1,s,1);
    return !lfl?!rfl?lans+rans:lans:rans;
}
void cover(int u,int v,int k)
{
    int tu=top[u],tv=top[v];
    while(tu^tv)
        if(d[tu]>d[tv])
        {
            cover(dfn[tu],dfn[u],k,1,1,s);
            tu=top[u=f[tu]];
        }
        else
        {
            cover(dfn[tv],dfn[v],k,1,1,s);
            tv=top[v=f[tv]];
        }
    if(d[u]>d[v])cover(dfn[v],dfn[u],k,1,1,s);
    else cover(dfn[u],dfn[v],k,1,1,s);
}
char str[3];
int main()
{
    for(int T=1;T--;){
        s=read;tot=0;int m=read;
        for(int i=1;i<=s;++i)va[i]=read;
        memset(b,0,sizeof(b));
        for(int i=1;i<s;++i)
            add(read,read,i<<1);
        dfs1(1,0);dfs2(1,1);
        build(1,s,1);
        while(m--){
            scanf("%s",str);
            int l=read,r=read;
            if(*str=='C')cover(l,r,read);
            else printf("%d\n",inquiry(l,r).h);
        }
    }
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!