트 리 데이터 구조 - LCT

6197 단어
목차
  • 트 리 의 데이터 구조 - LCT
  • 개술
  • 기본 개념
  • 핵심 조작
  • 기타 조작
  • 전체 템 플 릿
  • 트 리 데이터 구조 - LCT
    개술
    LCT 는 강력 한 트 리 데이터 구조 로 다음 작업 을 지원 합 니 다.
  • 체인 상의 구 화
  • 체인 에서 최고 치 를 구하 기
  • 체인 수정
  • 서브 트 리 수정
  • 자수 구 화
  • 뿌리 바 꾸 기
  • 나무 위의 한 변 을 부 러 뜨 린 다
  • 두 점 을 연결 하여 연결 후에 도 나무 가 될 것 을 보증한다.

  • 기본 개념
    LCT 는 나무의 실 사슬 을 나 누 는 것 으로 모든 변 을 실 변 과 허 변 으로 나 누 는 것 이다.
    중 사슬 분할 과 비슷 하 다. 각 점 에서 자 노드 에 연 결 된 실 사슬 은 기껏해야 하나 밖 에 없 는데 이 실 변 을 연결 하 는 아들 을 실 아들 이 라 고 부른다.
    일부 실제 연결 점 으로 구 성 된 체인 을 실제 체인 이 라 고 하 는데 실제 체인 간 에 공통점 이 없다 는 것 을 쉽게 발견 할 수 있다.
    주의해 야 할 것 은 실제 가장자리 에 없 는 점 (일부 잎 노드) 도 실제 가장자리 가 없 는 실제 체인 으로 여 긴 다 는 것 이다.
    그래서 실제 체인 사 이 는 반드시 허 변 으로 연 결 된 것 이다.
    동적 삭제 와 관련 된 작업 을 하려 면 splay 를 사용 하여 실제 체인 을 유지 합 니 다. splay 는 LCT 의 보조 트 리 입 니 다.
    이 곳 splay 의 깊이 는 중간 순서에 따라 엄 격 히 증가 합 니 다.
    splay 로 유지 하기 때문에 LCT 의 실제 변 화 는 동적 이 고 바 꿀 수 있 습 니 다.
    핵심 조작
    access (x): x 에서 뿌리 노드 까지 의 모든 변 을 실제 변 으로 하고 x 는 실제 아들 이 없다.
    이 건 플래시hu 의 블 로그
    조금 만 말씀 드 리 겠 습 니 다. 매번 조작 할 때마다 현재 연결 할 점 splay 를 현재 splay 의 뿌리 로 옮 깁 니 다. splay 의 깊이 가 중간 순서에 따라 점점 증가 하기 때문에 이때 뿌리 오른쪽 아들 은 반드시 전에 연 결 된 실제 체인 입 니 다. 제거 해 야 합 니 다.
    그래서 이전의 점 을 현재 뿌리 의 오른쪽 아들 에 게 연결 하면 된다.
    이때 일부 \ (fa, son, isroot \) 와 같은 정보 가 바 뀌 었 으 니 주의해 야 합 니 다 \ (push \) \(up\)
    void access(int x){
        for(int y=0;x;y=x,x=fa[x]){ //y     ,x        
            splay(x); ch[x][1]=y;
            push_up(x);
        }
    }

    기타 조작
  • makeroot 가 루트 를 바 꾸 어 access (x) 를 조작 한 후에 x 는 깊이 가 가장 큰 점 이기 때문에 splay (x) 이후 x 는 splay 에서 오른쪽 나무 가 없 을 것 이다. 이때 전체 splay 를 뒤 집 으 면 모든 점 의 깊이 가 거꾸로 된다. x 는 깊이 가 가장 작은 점 이 된다. 즉, 뿌리 노드
    void pushr(int x){
        swap(ch[x][0],ch[x][1]);
        r[x]^=1;
    }
    void makeroot(int x){
        access(x); splay(x);
        pushr(x);
    }
  • 이다.
  • findroot 은 나무의 뿌리 를 찾 아 두 점 사이 의 연관 성 을 판단 할 수 있다 (두 점 이 같은 나 무 는 유일 하 게 같은 뿌리
    int findroot(int x){
        access(x);splay(x);
        while(c[x][0]) push_down(x),x=ch[x][0];//        ,  push_down   x       ,     
        splay(x);//  splay    
        return 0;
    }
  • .
  • split 는 하나의 경 로 를 splay
    void spilt(int x,int y){
        makeroot(x);access(y);
        splay(y);
    }
  • 로 끌 어 올 립 니 다.
  • link 는 한 변 을 연결 하여 연결 되 는 지 한 그루 의 나무 가 합 법 적 인 지 를 보장 하지 않 습 니 다.
    int link(int x,int y){
        makeroot(x);
        if(findroot(y)==x) return 0;
        fa[x]=y; // x  y   
        return 1;
    }
    합 법 적 인 지 를 보장 합 니 다.
    void link(int x,int y){
        makeroot(x);
        fa[x]=y;
    }
    여기 연 결 된 변 은 허 변 입 니 다. (실제 체인 의 분할 이 편리 함 을 느 꼈 을 때
  • 컷 사 이 드 보증 존재:
    void cut(int x,int y){
        split(x,y);
        fa[x]=ch[y][0]=0;
    
    }
    이 사 이 드 가 존재 하지 않 을 때 는 어떤 상황 일 까요?
  • x 와 y 가 연결 되 지 않 음 (\ (findroot \)
  • 같은 splay 에서 직접 연결 되 지 않 았 습 니 다 (\ (f [y] = x \) 그리고 \ (! c [y] [0] \) (다른 점 이 어디 에 있 는 지 고려 하여 findroot 이후 x 가 뿌리 노드 에 이 르 렀 습 니 다. x 와 y 사이 에 조금 있 으 면 y 에서 뿌리 까지 의 경로 나 y 의 왼쪽 아들 에 만 있 을 수 있 습 니 다)
  • int cut(int x,int y){
        makeroot(x);
        if(findroot(y)!=x||fa[y]!=x||ch[y][0]) return 0;
        fa[y]=ch[x][1]=0;
        push_up(x);
        return 1;
    }
  • nroot naiive 의 조작 으로 이 점 이 현재 splay 의 루트 노드
    int nroot(int x){
        return (ch[fa[x]][1]==x||ch[fa[x]][0]==x);
    }
    가 아 닌 지 판단 합 니 다
  • splay 의 특수성 은 여기 splay 의 표 시 는 반드시 위 에서 아래로 내 려 야 합 니 다. 즉, 먼저 스 택 을 열 어 표 시 를 다 놓 고 회전 하 는 것 입 니 다
  • 전체 템 플 릿
    #include
    #include
    #include
    #include
    using namespace std;
    #define reg register int 
    #define il inline 
    #define ls ch[x][0]
    #define rs ch[x][1]
    int read(){
        int x=0,pos=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
        for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
        return pos?x:-x;
    }
    const int N = 400025;
    int fa[N],ch[N][2],v[N],s[N],st[N],r[N];
    il int nroot(int x){
        return ch[fa[x]][1]==x||ch[fa[x]][0]==x;
    }
    il int get(int x){
        return ch[fa[x]][1]==x;
    }
    il void push_up(int x){
        s[x]=v[x]^s[ls]^s[rs];
    }
    il void pushr(int x){
        swap(ls,rs);r[x]^=1;
    }
    il void push_down(int x){
        if(r[x]){
            if(ls) pushr(ls);
            if(rs) pushr(rs);
            r[x]=0;
        }
    }
    il void rotate(int x){
        int f=fa[x],g=fa[f],kx=get(x),kf=get(f);
        if(nroot(f)) ch[g][kf]=x;
        fa[x]=g;
        /*if(ch[x][kx^1])*/ fa[ch[x][kx^1]]=f;
        ch[f][kx]=ch[x][kx^1];
        fa[f]=x;ch[x][kx^1]=f;
        push_up(f);push_up(x);
    }
    il void push(int x){
        if(nroot(x)) push(fa[x]);
        push_down(x);
    }
    il void splay(int x){
        int f,g;
        push(x);//fuctional stack
        while(nroot(x)){
            f=fa[x],g=fa[f];
            if(nroot(f)){
                rotate(get(x)==get(f)?f:x);
            }
            rotate(x);
        }
    }
    il void access(int x){
        for(reg y=0;x;y=x,x=fa[x]){
            splay(x);rs=y;push_up(x);
        }
    }
    il void makeroot(int x){
        access(x);splay(x);pushr(x);
    }
    il void spilt(int x,int y){
        makeroot(x);
        access(y);splay(y);
    }
    il int findroot(int x){
        access(x);splay(x);
        while(ls) x=ls;
        splay(x);
        return x;
    }
    il void link(int x,int y){
        makeroot(x);
        if(findroot(y)!=x) fa[x]=y;
    }
    il void cut(int x,int y){
        makeroot(x);
        if(findroot(y)==x&&fa[y]==x&&!ch[y][0]){
            fa[y]=ch[x][1]=0;
            push_up(x);
        }
    }
    int n,m;
    int main(){
        n=read();m=read();
        for(reg i=1;i<=n;i++){
            v[i]=read();
        }
        for(reg i=1;i<=m;++i){
            int opt=read(),x=read(),y=read();
            if(opt==0){
                spilt(x,y);printf("%d
    ",s[y]); }else if(opt==1){ link(x,y); }else if(opt==2) cut(x,y); else splay(x),v[x]=y; } return 0; }

    나중에 본인 이 만 든 LCT 문 제 를 고 칠 수도 있어 요.
    본 고 를 창작 하 는 과정 에서 다음 과 같은 글 을 참고 했다.
  • [flash hu 사내 블 로그] [https://www.cnblogs.com/flashhu/p/8324551.html]
  • [NOI 급 의 강력 한 데이터 구조 - Link - cut - tree (동적 트 리) 학습 수기] [https://blog.csdn.net/qq_36551189/article/details/79152612]
  • 청 두 7 중의 LCT 과제 (조금 있 죠
  • Yang Zhe 2007 년 논문
  • 좋은 웹페이지 즐겨찾기