QTREE5 Link-Cut Tree

Posted llcsblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QTREE5 Link-Cut Tree相关的知识,希望对你有一定的参考价值。

\\(Problem\\ Link\\)

题目大意

你被给定一棵n个点的树,点从1到n编号。每个点可能有两种颜色:黑或白。我们定义dist(a,b)为点a至点b路径上的边个数。

一开始所有的点都是黑色的。

要求作以下操作:

0 i 将点i的颜色反转(黑变白,白变黑)

1 v 询问dist(u,v)的最小值。u点必须为白色(u与v可以相同),显然如果v是白点,查询得到的值一定是0。

特别地,如果作‘1‘操作时树上没有白点,输出-1.

思想分析

这题的动态点分治做法看我的总结

这题动态点分治做法还挺简单的,但是LCT做法就复杂一些,不过总体来说还是板子

我们定义\\(lmn[x],rmn[x]\\)分别代表在\\(splay\\)\\(x\\)的子树里深度最浅的点能够到达最近的白点的距离,

和深度最深的点能够到达最近的白点的距离

还要开个堆或者\\(multiset\\)维护一下子树中的\\(lmn\\)最小值.

这道题询问的是点到最近的白点的距离,所以就不需要维护子树信息了

不需要拉链,也就不用split,makert,findrt等一大堆操作了

这个时候LCT还是跑的很快的,比动态点分治快了一倍\\(qwq\\)

代码实现

/*
@Date    : 2019-09-10 17:14:38
@Author  : Adscn (adscn@qq.com)
@Link    : https://www.cnblogs.com/LLCSBlog
*/
#include<bits/stdc++.h>
using namespace std;
#define IL inline
#define RG register
#define gi getint()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
template<typename T>IL bool chkmax(T &x,const T &y)return x<y?x=y,1:0;
template<typename T>IL bool chkmin(T &x,const T &y)return x>y?x=y,1:0;
IL int getint()

    RG int xi=0;
    RG char ch=gc;
    bool f=0;
    while(!isdigit(ch))ch=='-'?f=1:f,ch=gc;
    while(isdigit(ch))xi=xi*10+ch-48,ch=gc;
    return f?-xi:xi;

template<typename T>
IL void pi(T k,char ch=0)

    if(k<0)k=-k,putchar('-');
    if(k>=10)pi(k/10,0);
    putchar(k%10+'0');
    if(ch)putchar(ch);

const int N=1e5+7;
const int inf=1e9;
int n;
namespace LCT
    int fa[N],ch[N][2],lmn[N],rmn[N],siz[N],col[N];
    multiset<int>s[N];
    multiset<int>::iterator it;
    #define ls(x) (ch[x][0])
    #define rs(x) (ch[x][1])
    #define s(x,k) (ch[x][k])
    inline bool ws(int x,int p)return rs(p)==x;
    inline bool nrt(int x)return ls(fa[x])==x||rs(fa[x])==x;
    inline int fir(int x)return s[x].empty()?inf:*s[x].begin();
    inline void pushup(int x)
        if(!x)return;
        siz[x]=siz[ls(x)]+siz[rs(x)]+1;
        lmn[x]=min(lmn[ls(x)],siz[ls(x)]+min(col[x]?0:inf,min(fir(x),lmn[rs(x)])+1));
        rmn[x]=min(rmn[rs(x)],siz[rs(x)]+min(col[x]?0:inf,min(fir(x),rmn[ls(x)])+1));
    
    inline void rotate(int x)
        int p=fa[x],g=fa[p];
        int t=ws(x,p),w=s(x,!t);
        if(nrt(p))s(g,ws(p,g))=x;s(x,!t)=p;s(p,t)=w;
        if(w)fa[w]=p;fa[p]=x;fa[x]=g;
        pushup(p);
    
    inline void Splay(int x)
        while(nrt(x))
        
            int p=fa[x],g=fa[p];
            if(nrt(p))rotate(ws(x,p)^ws(p,g)?x:p);
            rotate(x);
        
        pushup(x);
    
    inline void access(int x)
        for(int y=0;x;x=fa[y=x])
        
            Splay(x);
            s[x].insert(lmn[rs(x)]);
            if((it=s[x].lower_bound(lmn[y]))!=s[x].end())s[x].erase(it);
            rs(x)=y,pushup(x);
        
    
    inline void modify(int x)
        access(x),Splay(x);
        col[x]^=1;
        pushup(x);
    
    inline int query(int x)
        access(x);Splay(x);
        return rmn[x]>n?-1:rmn[x];
    

using namespace LCT;
struct edge
    int v,nxt;
e[N<<1|1];
int head[N],cnt;
inline void add(int u,int v)e[++cnt]=(edge)v,head[u],head[u]=cnt;
inline void init()memset(head,cnt=-1,sizeof head);
inline void dfs(int x,int p)

    for(int i=head[x],v;~i;i=e[i].nxt)
        if((v=e[i].v)^p)
            fa[v]=x,dfs(v,x);

int main(void)

    n=gi,lmn[0]=rmn[0]=inf;
    init();
    for(int i=1,u,v;i<n;++i)u=gi,v=gi,add(u,v),add(v,u);
    dfs(1,0);
    for(int i=1,m=gi;i<=m;++i)
    
        int opt=gi,x=gi;
        if(opt^1)modify(x);
        else pi(query(x),'\\n');
    
    return 0;

以上是关于QTREE5 Link-Cut Tree的主要内容,如果未能解决你的问题,请参考以下文章

SPOJ QTREE5 lct

模板Link-Cut Tree

Link-Cut Tree

SPOJQTREE7(Link-Cut Tree)

BZOJ2843极地旅行社(Link-Cut Tree)

动态树Link-Cut Tree(LCT)