• P2486 [SDOI2011]染色(树链剖分)


    多维护两个信息表示最左边的和最右边的两个点是什么颜色的。

    在更新的时候注意合并

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,ll> pll;
    const int N=1e6+10;
    const int M=2e6+10;
    const int inf=0x3f3f3f3f;
    const ll mod=998244353;
    int h[N],ne[N],e[N],idx;
    int times,pre[N],LC,RC;
    int n,m,val[N],sz[N],son[N],depth[N],dfn[N],top[N],father[N];
    struct node{
        int l,r;
        int cnt;
        int lazy;
        int ls,rs;
        int num;
    }tr[N<<1];
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    void dfs1(int u,int fa){
        sz[u]=1;
        int i;
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(j==fa)
                continue;
            father[j]=u;
            depth[j]=depth[u]+1;
            dfs1(j,u);
            sz[u]+=sz[j];
            if(sz[j]>sz[son[u]]){
                son[u]=j;
            }
        }
    }
    void dfs(int u,int x){
        int i;
        dfn[u]=++times,pre[times]=u;
        top[u]=x;
        if(!son[u])
            return ;
        dfs(son[u],x);
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(j==father[u]||j==son[u])
                continue;
            dfs(j,j);
        }
    }
    void pushup(int u){
        tr[u].num=tr[u<<1].num+tr[u<<1|1].num;
        tr[u].ls=tr[u<<1].ls,tr[u].rs=tr[u<<1|1].rs;
        if(tr[u<<1].rs==tr[u<<1|1].ls)
            tr[u].num--;
    }
    void build(int u,int l,int r){
        if(l==r){
            tr[u]={l,l,val[pre[l]],0,val[pre[l]],val[pre[l]],1};
        }
        else{
            tr[u]={l,r};
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
            pushup(u);
        }
    }
    void pushdown(int u){
        if(tr[u].lazy){
            int x=tr[u].lazy;
            tr[u<<1].num=tr[u<<1|1].num=1;
            tr[u<<1].lazy=tr[u<<1|1].lazy=x;
            tr[u<<1].ls=tr[u<<1].rs=tr[u<<1|1].rs=tr[u<<1|1].ls=x;
            tr[u].lazy=0;
        }
    }
    void modify(int u,int l,int r,int k){
        if(tr[u].l>=l&&tr[u].r<=r){
            tr[u].lazy=k;
            tr[u].ls=tr[u].rs=k;
            tr[u].num=1;
            return ;
        }
        pushdown(u);
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)
            modify(u<<1,l,r,k);
        if(r>mid)
            modify(u<<1|1,l,r,k);
        pushup(u);
    }
    int query(int u,int l,int r){
        if(tr[u].l>=l&&tr[u].r<=r){
            if(tr[u].l==l)
                LC=tr[u].ls;
            if(tr[u].r==r)
                RC=tr[u].rs;
            return tr[u].num;
        }
        pushdown(u);
        int mid=tr[u].l+tr[u].r>>1;
        ll sum=0;
        if(r<=mid)
            return query(u<<1,l,r);
        if(l>mid)
            return query(u<<1|1,l,r);
        sum=query(u<<1,l,r)+query(u<<1|1,l,r);
        if(tr[u<<1].rs==tr[u<<1|1].ls)
            sum--;
        return sum;
    }
    int querypath(int x,int y){
        int ans1=-1,ans2=-1;
        int sum=0;
        while(top[x]!=top[y]){
            if(depth[top[x]]<depth[top[y]]){
                swap(x,y);
                swap(ans1,ans2);
            }
            sum+=query(1,dfn[top[x]],dfn[x]);
            if(ans1==RC)
                sum--;
            ans1=LC;
            x=father[top[x]];
        }
        if(depth[x]>depth[y]){
            swap(x,y);
            swap(ans1,ans2);
        }
        sum+=query(1,dfn[x],dfn[y]);
        if(LC==ans1)
            sum--;
        if(RC==ans2)
            sum--;
        return sum;
    }
    void change(int x,int y,int c){
        while(top[x]!=top[y]){
            if(depth[top[x]]<depth[top[y]])
                swap(x,y);
            modify(1,dfn[top[x]],dfn[x],c);
            x=father[top[x]];
        }
        if(depth[x]>depth[y])
            swap(x,y);
        modify(1,dfn[x],dfn[y],c);
    }
    int main(){
        ios::sync_with_stdio(false);
        //freopen("1.in","r",stdin);
        cin>>n>>m;
        int i;
        memset(h,-1,sizeof h);
        for(i=1;i<=n;i++){
            cin>>val[i];
        }
        for(i=1;i<n;i++){
            int a,b;
            cin>>a>>b;
            add(a,b);
            add(b,a);
        }
        depth[1]=1;
        dfs1(1,-1);
        dfs(1,1);
        build(1,1,n);
        while(m--){
            string s;
            int a,b,c;
            cin>>s;
            if(s=="Q"){
                cin>>a>>b;
                cout<<querypath(a,b)<<endl;
            }
            else{
                cin>>a>>b>>c;
                change(a,b,c);
            }
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    Day 09 文件处理
    Day 08 字符编码
    day 07 猜年龄
    Day 07 元组/字典/集合/python深浅拷贝
    Day 06 猜年龄/三级菜单
    并发编程-Atomic的compareAndSet
    并发编程-多线程共享变量不安全
    Spring boot Junit单元测试回滚
    Java 不区分大小写比较字符串
    IDEA 设置html 和js热发布
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13613528.html
Copyright © 2020-2023  润新知