洛谷 [P2486] 染色

树剖+线段树维护连续相同区间个数

注意什么时候长度要减一

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll long long
using namespace std;
const int MAXN=100005;
int top[MAXN],head[MAXN],nume,n,m,dep[MAXN],fa[MAXN],son[MAXN],siz[MAXN],id[MAXN],wei[MAXN],wein[MAXN],ind;
struct edge{
    int to,nxt;
}e[MAXN<<1];
int init(){
    int rv=0,fh=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') fh=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        rv=(rv<<1)+(rv<<3)+c-'0';
        c=getchar();
    }
    return fh*rv;
}
void adde(int from,int to){
    e[++nume].to=to;
    e[nume].nxt=head[from];
    head[from]=nume;
}
void dfs1(int u,int rt){
    dep[u]=dep[rt]+1;
    fa[u]=rt;
    siz[u]=1;
    int ma=0;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(v==rt) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>ma){
            ma=siz[v];
            son[u]=v;
        }
    }
}
void dfs2(int u,int topf){
    top[u]=topf;
    id[u]=++ind;
    wein[ind]=wei[u];
    if(!son[u]) return;
    dfs2(son[u],topf);
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(v==fa[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}
struct SGT{
    int sum[MAXN<<2],tag[MAXN<<2],lc[MAXN<<2],rc[MAXN<<2];
    void PushUp(int rt){
        sum[rt]=sum[rt<<1]+sum[rt<<1|1]-(rc[rt<<1]==lc[rt<<1|1]);
        lc[rt]=lc[rt<<1];rc[rt]=rc[rt<<1|1];
    }
    void build(int l,int r,int rt){
        if(l==r){
            sum[rt]=1;
            lc[rt]=rc[rt]=wein[l];
            return ;
        }
        int mid=(l+r)>>1;
        build(lson);
        build(rson);
        PushUp(rt);
    }
    void PushDown(int rt){
        if(tag[rt]){
            tag[rt<<1]=tag[rt<<1|1]=tag[rt];
            sum[rt<<1]=sum[rt<<1|1]=1;
            lc[rt<<1]=rc[rt<<1]=lc[rt<<1|1]=rc[rt<<1|1]=tag[rt];
            tag[rt]=0;
        }
    }
    void Update(int L,int R,int add,int l,int r,int rt){
        if(L<=l&&r<=R){
            sum[rt]=1;
            lc[rt]=rc[rt]=add;
            tag[rt]=add;
            return;
        }
        PushDown(rt);
        int mid=(l+r)>>1;
        if(L<=mid) Update(L,R,add,lson);
        if(mid<R) Update(L,R,add,rson);
        PushUp(rt);
    }
    int Query(int L,int R,int l,int r,int rt){
        if(L<=l&&r<=R){
            return sum[rt];
        }
        PushDown(rt);
        int mid=(l+r)>>1;
        int ans=0,f=0;
        if(L<=mid) ans+=Query(L,R,lson),f++;
        if(mid<R) ans+=Query(L,R,rson),f++;
        if(f==2){
            ans-=(rc[rt<<1]==lc[rt<<1|1]);
        }
        PushUp(rt);
        return ans;
    }
    int find(int loc,int l,int r,int rt){
        if(l==r){
            return rc[rt];
        }
        PushDown(rt);
        int mid=(l+r)>>1;
        int ans=0;
        if(loc<=mid) ans=find(loc,lson);
        else ans=find(loc,rson);
        PushUp(rt);
        return ans;
    }
}sgt;
void UpdateRange(int u,int v,int add){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        sgt.Update(id[top[u]],id[u],add,1,n,1);
        u=fa[top[u]];
    }
    if(dep[u]>dep[v]) swap(u,v);
    sgt.Update(id[u],id[v],add,1,n,1);
}
int QueryRange(int u,int v){
    int ans=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        ans+=sgt.Query(id[top[u]],id[u],1,n,1);
        ans-=(sgt.find(id[fa[top[u]]],1,n,1)==sgt.find(id[top[u]],1,n,1));
        u=fa[top[u]];
    }
    if(dep[u]>dep[v]) swap(u,v);
    ans+=sgt.Query(id[u],id[v],1,n,1);
    return ans;
}
int main(){
    n=init();m=init();
    for(int i=1;i<=n;i++) wei[i]=init();
    for(int i=1;i<n;i++){
        int u=init(),v=init();
        adde(u,v);adde(v,u);
    }
    dep[1]=1;
    dfs1(1,0);
    dfs2(1,1);
    sgt.build(1,n,1);
    char s[10];
    /*for(int i=1;i<=n;i++) printf("%d ",wein[id[i]]);
    cout<<endl;
    for(int i=1;i<=n;i++) printf("%d ",sgt.find(id[i],1,n,1));
    cout<<endl;*/
    for(int i=1;i<=m;i++){
        scanf("%s",s);
        if(s[0]=='C'){
            int a=init(),b=init(),t=init();
            UpdateRange(a,b,t);
            /*for(int i=1;i<=n;i++) printf("%d ",sgt.find(id[i],1,n,1));
            cout<<endl;*/
        }else {
            int a=init(),b=init();
            printf("%d\n",QueryRange(a,b));
        }
    }
    for(int i=1;i<=n;i++) ;
    return 0;
}

转载于:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8410431.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值