[学习笔记]LCT进阶操作 LCT总结——应用篇(附题单)(LCT)

LCT总结——应用篇(附题单)(LCT)

一般都是维护链的操作。split即可搞定。

进阶操作的话,处理好辅助树和原树的关系即可搞定。

其实,最大的区别就是,splay随便转,辅助树形态变了,但是原树形态不变,makert会让原树形态变化

LCT维护子树信息

真儿子会splay的时候各种变化,但是虚儿子只会在access和link的时候发生变化,其他的时候可以理解为跟着转。

以处理子树sz为例,

处理虚边子树sz,总sz(包括实边)两个

pushup注意下。

access和link注意下。

需要真正找子树信息的时候,考虑把x的后继access掉,把xsplay到根,然后总sz就是子树sz了。

模板题:

[BJOI2014]大融合

注意查询x,y的子树大小的话,makert(x),access(y),splay(y).

其实x,y直接连通,所以现在是一个长度为2的链,y是根,x是y的右儿子,然后直接(si[y]+1)*(si[x]+1)即可。(si[x]+1可以换成s[x])

#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
const int N=1e5+5;
int ch[N][2],fa[N],si[N],s[N];
int r[N];
int n,q;
bool nrt(int x){
    return (ch[fa[x]][0]==x)||(ch[fa[x]][1]==x);
}
void pushup(int x){
    if(x) s[x]=s[ch[x][0]]+s[ch[x][1]]+si[x]+1;
}
void rev(int x){
    swap(ch[x][0],ch[x][1]);
    r[x]^=1;
}
void pushdown(int x){
    if(r[x]){
        rev(ch[x][0]);rev(ch[x][1]);
        r[x]=0;
    }
}
void rotate(int x){
    int y=fa[x],d=ch[fa[x]][1]==x;
    fa[ch[y][d]=ch[x][!d]]=y;
    if(nrt(y)) ch[fa[x]=fa[y]][ch[fa[y]][1]==y]=x;
    else fa[x]=fa[y];
    ch[fa[y]=x][!d]=y;
    pushup(y);
}
int sta[N],top;
void splay(int x){
    int y=x;
    sta[++top]=y;
    while(nrt(y)) y=fa[y],sta[++top]=y;
    while(top) pushdown(sta[top--]);
    int z;
    while(nrt(x)){
        y=fa[x],z=fa[y];
        if(nrt(y)){
            rotate(((ch[z][0]==y)==(ch[y][0]==x))?y:x);
        }
        rotate(x);
    }
    pushup(x);
}
void access(int x){
    for(int y=0;x;y=x,x=fa[x]){
        splay(x);
        si[x]-=s[y];
        si[x]+=s[ch[x][1]];
        ch[x][1]=y;
        pushup(x);
    }
}
void makert(int x){
    access(x);
    splay(x);
    rev(x);
}
void link(int x,int y){
    makert(x);
    makert(y);
    si[y]+=s[x];
    s[y]+=s[x];
    fa[x]=y;
    pushup(y);
}
int query(int x,int y){
    makert(x);access(y);
    return (long long)(si[x]+1)*(si[y]+1);
}
int main(){
    rd(n);rd(q);
    char cc[2];
    int x,y;
    for(reg i=1;i<=n;++i){
        si[i]=0;s[i]=1;
    }
    while(q--){
        scanf("%s",cc+1);
        rd(x);rd(y);
        if(cc[1]=='A'){
            link(x,y);
        }else{
            printf("%d\n",query(x,y));        
        }
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2018/12/18 11:13:18
*/
大融合

LCT维护联通块信息(边双联通分量)

LCT维护边权(常用生成树)

LCT维护子树信息

LCT维护树上染色联通块

猜你喜欢

转载自www.cnblogs.com/Miracevin/p/10140719.html
LCT