P2486 [SDOI2011] 染色

题意

给一棵树,修改是链赋值,查询是求链的极长同色连续段数量。

思路

简单题,用树剖维护。
线段树的每个区间维护 \(4\) 个信息:懒标记,区间极长同色连续段数量,左端点颜色,右端点颜色,然后直接暴力维护即可。

代码

/*
Luogu P2486 [SDOI2011] 染色
2026-04-03
*/
#include<bits/stdc++.h>
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T&x){
        x=0;char c=getchar();bool f=0;
        while(!isdigit(c)) c=='-'?f=1:0,c=getchar();
        while(isdigit(c)) x=x*10+c-'0',c=getchar();
        f?x=-x:0;
    }
    template<typename T>
    inline void write(T x){
        if(x==0){putchar('0');return ;}
        x<0?x=-x,putchar('-'):0;short st[50],top=0;
        while(x) st[++top]=x%10,x/=10;
        while(top) putchar(st[top--]+'0');
    }
    inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}
    inline void write(char c){putchar(c);}
    inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}
    inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}
    template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}
    template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}
    template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
const int maxn=100010;
vector<int>e[maxn];
int n,m,w[maxn];
class Segment_Tree{
private:
    struct node{int cnt,be_col,en_col,tag;}t[maxn*8];
    void add_tag(int u,int c){
        t[u].tag=c;
        t[u].be_col=t[u].en_col=c;
        t[u].cnt=1;
    }
    void down(int u){
        if(t[u].tag==0) return ;
        add_tag(u<<1,t[u].tag),add_tag(u<<1|1,t[u].tag);
        t[u].tag=0;
    }
    void push_up(int u){
        t[u].be_col=t[u<<1].be_col,t[u].en_col=t[u<<1|1].en_col;
        t[u].cnt=t[u<<1].cnt+t[u<<1|1].cnt;
        if(t[u<<1].en_col==t[u<<1|1].be_col) t[u].cnt--;
    }
    void update(int u,int l,int r,int ll,int rr,int c){
        if(l>rr||r<ll) return ;
        if(ll<=l&&r<=rr){add_tag(u,c);return ;}
        down(u);
        int mid=l+r>>1;
        update(u<<1,l,mid,ll,rr,c),update(u<<1|1,mid+1,r,ll,rr,c);
        push_up(u);
    }
    tuple<int,int,int>query(int u,int l,int r,int ll,int rr){
        if(ll<=l&&r<=rr) return{t[u].be_col,t[u].en_col,t[u].cnt};
        down(u);
        int mid=l+r>>1;
        if(mid<ll) return query(u<<1|1,mid+1,r,ll,rr);
        if(mid>=rr) return query(u<<1,l,mid,ll,rr);
        auto[be1,en1,cnt1]=query(u<<1,l,mid,ll,rr);
        auto[be2,en2,cnt2]=query(u<<1|1,mid+1,r,ll,rr);
        cnt1+=cnt2;
        if(en1==be2) cnt1--;
        return{be1,en2,cnt1};
    }
public:
    void update(int l,int r,int c){update(1,1,n,l,r,c);}
    tuple<int,int,int>query(int l,int r){return query(1,1,n,l,r);}
}t;
namespace HLD{
    int fa[maxn],deep[maxn],sz[maxn],son[maxn],top[maxn],dfn[maxn],cnt_dfn;
    void dfs1(int u,int father=0){
        fa[u]=father,sz[u]=1;
        deep[u]=deep[fa[u]]+1;
        for(int v:e[u]){
            if(v==fa[u]) continue;
            dfs1(v,u);
            sz[u]+=sz[v];
            if(sz[son[u]]<sz[v]) son[u]=v;
        }
    }
    void dfs2(int u,int Top){
        dfn[u]=++cnt_dfn;
        top[u]=Top;
        if(son[u]) dfs2(son[u],Top);
        for(int v:e[u]){
            if(v==fa[u]||v==son[u]) continue;
            dfs2(v,v);
        }
    }
    void build(){
        dfs1(1),dfs2(1,1);
        for(int i=1;i<=n;i++) t.update(dfn[i],dfn[i],w[i]);
    }
    void update(int u,int v,int c){
        while(top[u]!=top[v]){
            if(deep[top[u]]<deep[top[v]]) swap(u,v);
            t.update(dfn[top[u]],dfn[u],c);
            u=fa[top[u]];
        }
        if(deep[u]>deep[v]) swap(u,v);
        t.update(dfn[u],dfn[v],c);
    }
    int query(int u,int v){
        int ltu=0,ltv=0,ans=0;
        while(top[u]!=top[v]){
            if(deep[top[u]]<deep[top[v]]) swap(u,v),swap(ltu,ltv);
            auto[be,en,cnt]=t.query(dfn[top[u]],dfn[u]);
            ans+=cnt;
            if(en==ltu) ans--;
            ltu=be;
            u=fa[top[u]];
        }
        if(deep[u]>deep[v]) swap(u,v),swap(ltu,ltv);
        auto[be,en,cnt]=t.query(dfn[u],dfn[v]);
        ans+=cnt;
        if(ltu==be) ans--;
        if(ltv==en) ans--;
        return ans;
    }
};
signed main(){
    read(n,m);
    for(int i=1;i<=n;i++) read(w[i]);
    for(int i=1;i<n;i++){
        int u,v;read(u,v);
        e[u].push_back(v),e[v].push_back(u);
    }
    HLD::build();
    for(int i=1;i<=m;i++){
        char op;int a,b,c;read(op,a,b);
        if(op=='C'){
            read(c);
            HLD::update(a,b,c);
        }
        else write(HLD::query(a,b)),write("\n");
    }
    return 0;
}
posted @ 2026-04-03 21:35  Link-Cut_Trees  阅读(3)  评论(0)    收藏  举报