• 【Luogu】P2486染色(树链剖分)


      题目链接

      线段树维护左端颜色,右端颜色,颜色段数量。

      合并的时候看左子树的右端颜色是不是等于右子树的左端颜色,如果等于那么颜色段数量要-1S

      然后在树剖跳链的时候搞同样的操作qwq

      然后就没有然后了

      

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    #include<cstdlib>
    #define maxn 500000
    #define left (rt<<1)
    #define right (rt<<1|1)
    #define mid ((l+r)>>1)
    #define lson l,mid,left
    #define rson mid+1,r,right
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int n,m;
    int tag[maxn*2];
    int deep[maxn];
    int dfn[maxn],ID;
    int back[maxn];
    int q[maxn];
    int son[maxn];
    int top[maxn];
    int father[maxn];
    int size[maxn];
    
    struct Edge{
        int next,to;
    }edge[maxn*2];
    int head[maxn],num;
    inline void add(int from,int to){
        edge[++num]=(Edge){head[from],to};
        head[from]=num;
    }
    
    struct Node{
        int lcol,rcol,ncol;
        Node operator +(const Node a){
            Node ans=(Node){lcol,a.rcol,ncol+a.ncol};
            if(rcol==a.lcol)    ans.ncol--;
            return ans;
        }
    }tree[maxn*2];
    
    inline void pushup(int rt){
        tree[rt]=tree[left]+tree[right];
    }
    
    inline void pushdown(int rt){
        if(tag[rt]==0)    return;
        tag[left]=tag[right]=tag[rt];
        tree[left].lcol=tree[right].lcol=tree[left].rcol=tree[right].rcol=tag[rt];
        tree[left].ncol=tree[right].ncol=1;
        tag[rt]=0;
    }
    
    void build(int l,int r,int rt){
        if(l==r){
            int last=back[l];
            tree[rt]=(Node){q[last],q[last],1};
            return;
        }
        build(lson);
        build(rson);
        pushup(rt);
    }
    
    void update(int from,int to,int num,int l,int r,int rt){
        if(from<=l&&to>=r){
            tree[rt]=(Node){num,num,1};
            tag[rt]=num;
            return;
        }
        pushdown(rt);
        if(from<=mid)    update(from,to,num,lson);
        if(to>mid)        update(from,to,num,rson);
        pushup(rt);
        return;
    }
    
    int query(int from,int to,int l,int r,int rt){
        if(from<=l&&to>=r)    return tree[rt].ncol;
        pushdown(rt);
        int ans=0;
        if(from<=mid)    ans+=query(from,to,lson);
        if(to>mid)        ans+=query(from,to,rson);
        if(from<=mid&&to>mid)
            if(tree[left].rcol==tree[right].lcol)    ans--;
        return ans;
    }
    
    int qucol(int o,int l,int r,int rt){
        if(l==r)    return tree[rt].lcol;
        pushdown(rt);
        if(o<=mid)    return qucol(o,lson);
        else        return qucol(o,rson);
    }
    
    void findfs(int x,int fa){
        deep[x]=deep[fa]+1;    size[x]=1;    father[x]=fa;
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(to==fa)    continue;
            findfs(to,x);
            size[x]+=size[to];
            if(son[x]==0||size[son[x]]<size[to])    son[x]=to;
        }
    }
    
    void unidfs(int x,int Top){
        top[x]=Top;
        dfn[x]=++ID;    back[ID]=x;
        if(son[x]==0)    return;
        unidfs(son[x],Top);
        for(int i=head[x];i;i=edge[i].next){
            int to=edge[i].to;
            if(to==father[x]||to==son[x])    continue;
            unidfs(to,to);
        }
    }
    
    void uplink(int from,int to,int num){
        while(top[from]!=top[to]){
            if(deep[top[from]]<deep[top[to]])    swap(from,to);
            update(dfn[top[from]],dfn[from],num,1,n,1);
            from=father[top[from]];
        }
        if(deep[from]>deep[to])    swap(from,to);
        update(dfn[from],dfn[to],num,1,n,1);
    }
    
    int qulink(int from,int to){
        int ans=0;
        while(top[from]!=top[to]){
            if(deep[top[from]]<deep[top[to]])    swap(from,to);
            ans+=query(dfn[top[from]],dfn[from],1,n,1);
            from=top[from];
            if(qucol(dfn[from],1,n,1)==qucol(dfn[father[from]],1,n,1))    ans--;
            from=father[from];
        }
        if(deep[from]>deep[to])    swap(from,to);
        ans+=query(dfn[from],dfn[to],1,n,1);
        return ans;
    }
    
    int main(){
        n=read(),m=read();
        for(int i=1;i<=n;++i)    q[i]=read();
        for(int i=1;i<n;++i){
            int from=read(),to=read();
            add(from,to);
            add(to,from);
        }
        findfs(1,1);
        unidfs(1,1);
        build(1,n,1);
        for(int i=1;i<=m;++i){
            char ch[10];    int a,b;
            scanf("%s%d%d",ch,&a,&b);
            if(ch[0]=='Q')    printf("%d
    ",qulink(a,b));
            else if(ch[0]=='C'){
                int c=read();
                uplink(a,b,c);
            }
        }
        return 0;
    }
  • 相关阅读:
    zoj 2110
    zoj 2376 Ants
    zoj 2256 Mincost
    企业版app在iOS8上无法安装的几个问题解决
    源码推荐(8.05):一行代码实现多风格的推送小红点,效果很好的跑马灯
    iOS在支持arc的工程中,导入不支持arc的第三方的插件
    一个异步加载图片的公用类: EGOImageLoading
    一款轻量级的 iOS 图像缓存
    UIGestureRecognizer学习笔记
    IOS两个App应用之间的跳转
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8269445.html
Copyright © 2020-2023  润新知