洛谷7735:[NOI2021] 轻重边——题解

https://www.luogu.com.cn/problem/P7735

网上的做法我找到的分两种,一种是染色法,这种做法好写,但是我不认为以我的脑子能想出来。另一种是暴力维护,因为易知与任何一点相关联的重边最多只有两条,好想不好写。

当然这里就说下前者的做法。每次操作时相当于为路径上的所有点染上一种与众不同的颜色。而至于重边的判断,则是边的端点颜色相同(且不为0)。由此树链剖分维护即可。

(这种做法是咋想到的啊……要不然就是我题刷少了QAQ)

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+5;
inline int read(){
    int X=0,w=0;char ch=0;
    while(ch<'0'||ch>'9'){w|=ch=='-';ch=getchar();}
    while(ch>='0'&&ch<='9')X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
inline int check(int l,int r){
    return (l==r)&&l;
}
struct Ans{
    int l,r,sum;
    Ans(){
        l=r=sum=0;
    }
    Ans(int _l,int _r,int _sum){
        l=_l;r=_r;sum=_sum;
    }
    Ans operator +(const Ans& b)const{
        int L=(!l)?b.l:l;
        int R=(!b.r)?r:b.r;
        return Ans(L,R,sum+b.sum+check(r,b.l));
    }
};
struct node{
    int to,nxt;
}e[N<<1];
struct tree{
    int lazy;
    Ans d;
}t[N<<2];
int head[N],cnt,tot,n,m,rt;
int fa[N],pos[N],idx[N],son[N],size[N],dep[N],top[N];
inline void add(int u,int v){
    e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
}
void dfs1(int u){
    size[u]=1;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(fa[u]==v)continue;
        fa[v]=u;dep[v]=dep[u]+1;
        dfs1(v);
        size[u]+=size[v];
        if(!son[u]||size[son[u]]<size[v])son[u]=v;
    }
}
void dfs2(int u,int anc){
    pos[u]=++tot;idx[tot]=u;top[u]=anc;
    if(!son[u])return;
    dfs2(son[u],anc);
    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);
    }
}
inline void init(){
    dep[rt]=1;
    dfs1(rt);
    dfs2(rt,rt);
}
void build(int a,int l,int r){
    if(l==r){
        t[a].lazy=0;
        t[a].d=Ans();
        return;
    }
    int mid=(l+r)>>1;
    build(a<<1,l,mid);build(a<<1|1,mid+1,r);
    t[a].lazy=0;
    t[a].d=t[a<<1].d+t[a<<1|1].d;
}
void pushdown(int a,int l,int r){
    int mid=(l+r)>>1;
    if(t[a].lazy){
        t[a<<1].lazy=t[a].lazy;
        t[a<<1|1].lazy=t[a].lazy;
        t[a<<1].d=Ans(t[a].lazy,t[a].lazy,mid-l);
        t[a<<1|1].d=Ans(t[a].lazy,t[a].lazy,r-mid-1);
        t[a].lazy=0;
    }
    return;
}
inline Ans query(int a,int l,int r,int l1,int r1){
    if(r1<l||r<l1)return Ans();
    if(l1<=l&&r<=r1)return t[a].d;
    int mid=(l+r)>>1;pushdown(a,l,r);
    Ans tmp=query(a<<1,l,mid,l1,r1)+query(a<<1|1,mid+1,r,l1,r1);
    return tmp;
}
inline void modify(int a,int l,int r,int l1,int r1,int v){
    if(r1<l||r<l1)return;
    if(l1<=l&&r<=r1){
        t[a].lazy=v;
        t[a].d=Ans(v,v,r-l);
        return;
    }
    int mid=(l+r)>>1;pushdown(a,l,r);
    modify(a<<1,l,mid,l1,r1,v);modify(a<<1|1,mid+1,r,l1,r1,v);
    t[a].d=t[a<<1].d+t[a<<1|1].d;
}
inline int pathquery(int x,int y){
    int op=0;
    Ans ansl,ansr;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]){
            swap(x,y);op^=1;
        }
        if(!op) ansl=query(1,1,n,pos[top[x]],pos[x])+ansl;
        else ansr=query(1,1,n,pos[top[x]],pos[x])+ansr;
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]){
        swap(x,y);op^=1;
    }
    Ans ans=query(1,1,n,pos[x],pos[y]);
    swap(ansl.l,ansl.r);
    if(op)swap(ans.l,ans.r);
    ans=ansl+ans+ansr;
    return ans.sum;
}
inline void pathmodify(int x,int y,int z){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        modify(1,1,n,pos[top[x]],pos[x],z);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    modify(1,1,n,pos[x],pos[y],z);
}
void initforcase(){
    cnt=tot=0;rt=1;
    memset(head,0,sizeof(head));
    memset(son,0,sizeof(son));
}
int main(){
    int T=read();
    while(T--){
        initforcase();
        n=read(),m=read();
        for(int i=1;i<n;i++){
            int u=read(),v=read();
            add(u,v);add(v,u);
        }
        init();build(1,1,n);
        for(int i=1;i<=m;i++){
            int op=read();
            if(op==1){
                int x=read(),y=read(),z=i;
                pathmodify(x,y,z);
            }
            if(op==2){
                int x=read(),y=read();
                printf("%d\n",pathquery(x,y));
            }
        }
    }
    
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

 +本文作者:luyouqi233。               +

 +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

posted @ 2021-08-02 01:07  luyouqi233  阅读(92)  评论(0编辑  收藏  举报