• [2020多校联考]染色相邻的边


    Solution

    可以发现,如一条边是白边,那么连接它的两个端点最后一次被修改,是同一个修改操作造成的,否则它就会被其中一个修改操作变成黑边。又发现如果一条边的两个端点修改时间戳不一样,就会在查询的链里面多开出一段颜色,所以统计一条链上的黑边个数,就是统计有多少条边的两个端点时间戳不同,即整条链上的颜色段数减一。就转换成了这道题。修改操作转换成修改整条链上点的时间戳(颜色)。

    #include<stdio.h>
    #define lid id<<1
    #define rid id<<1|1
    #define N 200007
    
    template<class T>
    inline void read(T &x){
        x=0;T flag=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')flag*=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        x*=flag;
    }
    
    struct Node{
        int l,r,sum,cov;
        Node(){l=r=sum=cov=0;}
        Node(int a,int b,int c,int d){l=a,r=b,sum=c,cov=d;}
    }tr[N<<2];
    
    struct E{
        int next,to;
    }e[N<<1];
    
    int n,m,a[N],cnt,tot,head[N];
    int sz[N],son[N],dep[N],fa[N],top[N],in[N];
    
    inline void swap(int &x,int &y){x^=y,y^=x,x^=y;}
    inline void update(int id){
        tr[id].l=tr[lid].l,tr[id].r=tr[rid].r;
        tr[id].sum=tr[lid].sum+tr[rid].sum-(tr[lid].r==tr[rid].l);
    }
    
    inline void add(int id,int to){
        e[++cnt]=(E){head[id],to};
        head[id]=cnt;
    }
    
    void dfs1(int u){
        sz[u]=1;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==fa[u]) continue;
            fa[v]=u,dep[v]=dep[u]+1;
            dfs1(v);
            sz[u]+=sz[v];
            if(sz[v]>sz[son[u]]) son[u]=v;
        }
    }
    
    void dfs2(int u,int tp){
        in[u]=++tot,top[u]=tp;
        if(!son[u]) return ;
        dfs2(son[u],tp);
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==fa[u]||v==son[u]) continue;
            dfs2(v,v);
        }
    }
    
    void build(int id,int lf,int rf){
        if(lf==rf){
            tr[id].sum=1;
            tr[id].l=tr[id].r=-lf;
        }else{
            int mid=(lf+rf)>>1;
            build(lid,lf,mid);
            build(rid,mid+1,rf);
            update(id);
        }
    }
    
    int l,r,val;
    inline void pushup(int id,int v){
        tr[id].sum=1,tr[id].cov=v;
        tr[id].l=tr[id].r=v;
    }
    
    inline void pushdown(int id){
        pushup(lid,tr[id].cov);
    	pushup(rid,tr[id].cov);
        tr[id].cov=0;
    }
    
    void modify(int id,int lf,int rf){
        if(l<=lf&&rf<=r) pushup(id,val);
        else{
            int mid=(lf+rf)>>1;
            if(tr[id].cov) pushdown(id);
            if(l<=mid) modify(lid,lf,mid);
            if(r>mid) modify(rid,mid+1,rf);
            update(id);
        }
    }
    
    inline void modify_path(){
        int u=l,v=r;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            l=in[top[u]],r=in[u];
            modify(1,1,n);
            u=fa[top[u]];
        }
        if(dep[u]<dep[v]) swap(u,v);
        l=in[v],r=in[u],modify(1,1,n);
    }
    
    Node query(int id,int lf,int rf){
        if(l<=lf&&rf<=r) return tr[id];
        else{
            int mid=(lf+rf)>>1;
            if(tr[id].cov) pushdown(id);
            if(r<=mid) return query(lid,lf,mid);
            else if(l>mid) return query(rid,mid+1,rf);
            else{
                Node ls=query(lid,lf,mid);
                Node rs=query(rid,mid+1,rf);
                Node now(ls.l,rs.r,ls.sum+rs.sum,0);
                if(ls.r==rs.l) now.sum--;
                return now;
            } 
        }
    }
    
    inline int query_path(){
        int u=l,v=r,a1=0,a2=0,ret=0;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])
                swap(u,v),swap(a1,a2);
            l=in[top[u]],r=in[u];
            Node t=query(1,1,n);
            if(t.r==a1) t.sum--;
            ret+=t.sum,a1=t.l;
            u=fa[top[u]];
        }
        if(dep[u]<dep[v]) swap(u,v),swap(a1,a2);
        l=in[v],r=in[u];
        Node t=query(1,1,n);
        if(t.r==a1) t.sum--;
        if(t.l==a2) t.sum--;
        return ret+t.sum;
    }
    
    int main(){
        freopen("colour.in","r",stdin);
        freopen("colour.out","w",stdout);
        read(n);int u,v;
        for(int i=1;i<n;i++){
            read(u),read(v);
            add(u,v),add(v,u);
        }
        fa[1]=1,dep[1]=1,dfs1(1);
        dfs2(1,1),build(1,1,n);
        read(m);
        for(int i=1,opt;i<=m;i++){
            read(opt),read(l),read(r);
            if(opt) val=i,modify_path();
            else printf("%d
    ",query_path()-1);
        }
    }
    
  • 相关阅读:
    Java后端知识体系
    HashMap底层实现整理
    Java线程池
    Spring Boot+Dubbo 入门
    Go 代码记录(一)
    Servlet 复习
    Spring Cloud(二)Eureka:服务注册与发现
    Spring Cloud (一)概述
    数据结构基础知识
    容器技术-Docker入门
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14048750.html
Copyright © 2020-2023  润新知