LCT教程

lct是一种动态树,用来维护一些动态加边删边的操作的东西.他主要用到几个操作,其实这个算法和树链刨分有点像,但是不能用线段树简单维护,所以我们要用多棵平衡树来维护树上的一个个子树,然后就进行一些很秀的操作.详情见这个博客:FlashHu

这个博客讲的是真的好,特别适合新手看,而且特别细节,(特别带劲).现在我就可以上代码:

模板:

#include <iostream>
#include <cassert>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
#define duke(i, a, n) for (register int i = a; i <= n; i++)
#define lv(i, a, n) for (register int i = a; i >= n; i--)
#define clean(a) memset(a, 0, sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x) {
    char c;
    bool op = 0;
    while (c = getchar(), c < '0' || c > '9')
        if (c == '-')
            op = 1;
    x = c - '0';
    while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0';
    if (op)
        x = -x;
}
template <class T>
void write(T x) {
    if (x < 0)
        putchar('-'), x = -x;
    if (x >= 10)
        write(x / 10);
    putchar('0' + x % 10);
}
const int N = 300009;
struct node {
    int fa, ch[2], rev, v, s;
} a[N];
int st[N];
#define O(a) cout << #a << " "  << a << endl;
int n, m;
bool isroot(int x) { return !(a[a[x].fa].ch[0] == x || a[a[x].fa].ch[1] == x); }
void pushr(int x) {
    swap(a[x].ch[0], a[x].ch[1]);
    a[x].rev ^= 1;
}
void push_down(int k) {
    if (a[k].rev) {
        if (a[k].ch[0])
            pushr(a[k].ch[0]);
        if (a[k].ch[1])
            pushr(a[k].ch[1]);
        a[k].rev ^= 1;
    }
}
void push_up(int x) { a[x].s = a[a[x].ch[0]].s ^ a[a[x].ch[1]].s ^ a[x].v; }
void connect(int x, int fa, int son) {
    a[x].fa = fa;
    a[fa].ch[son] = x;
}
int iden(int x) { return a[a[x].fa].ch[0] == x ? 0 : 1; }
void rotate(int x) {
    int y = a[x].fa;
    int mroot = a[y].fa;
    int mrootson = iden(y);
    int yson = iden(x);
    int b = a[x].ch[yson ^ 1];
    if (!isroot(y)) {
        a[mroot].ch[mrootson] = x;
    }
    a[x].fa = mroot;
    connect(b, y, yson);
    connect(y, x, yson ^ 1);
    push_up(y);
    push_up(x);
}
void splay(int x) {
    int top = 0;int  i;
    st[++top] = x;
    for (i = x; !isroot(i); i = a[i].fa) {
        st[++top] = a[i].fa;
    }
    for (int i = top; i >= 1; i--) {
        push_down(st[i]);
    }
    while (!isroot(x)) {
        int y = a[x].fa;
        if (isroot(y)) {
            rotate(x);
        } else if (iden(x) == iden(y)) {
            rotate(y);
            rotate(x);
        } else {
            rotate(x);
            rotate(x);
        }
    }
    push_up(x);
}
void access(int x) {
    int t = 0;
    while (x) {
        splay(x);
        a[x].ch[1] = t;
        push_up(x);
        t = x;
        x = a[x].fa;
    }
}
void make_root(int x) {
    access(x);
    splay(x);
    //    a[a[x].ch[0]].rev ^= 1;
    //    a[a[x].ch[1]].rev ^= 1;
    pushr(x);
    //    swap(a[x].ch[0],a[x].ch[1]);
    //    push_down(x);
}
void split(int x, int y) {
    // if (x <= n && y <= n) {
        make_root(x);
        access(y);
        splay(y);
    // }
}
int findroot(int x) {
    access(x);
    splay(x);
    push_down(x);
    while (a[x].ch[0]){
        push_down(a[x].ch[0]);
        x = a[x].ch[0];
    }
    return x;
}
void link(int x, int y) {
    make_root(x);
    int t = findroot(y);
    assert(t);
    if ( t != x)
        a[x].fa = y;
}
void cut(int x, int y) {
    make_root(x);
    int t = findroot(y);
    assert(t);
    if (t == x && a[x].fa == y && !a[x].ch[1]) {
        a[x].fa = a[y].ch[0] = 0;
        push_up(y);
    }
}
int main() {
//    freopen("in.in","r",stdin);
    int x, y, typ;
    read(n);
    read(m);
    duke(i, 1, n) { read(a[i].v); push_up(i); }
    int oup = 0;
    duke(mi,1,m){
        read(typ);
        read(x);
        read(y);
        if (typ == 0) {
            split(x, y);
            printf("%d\n", a[y].s);
            ++oup;

        } else if (typ == 1) {
            link(x, y);
        } else if (typ == 2) {
            cut(x, y);
        } else {
            splay(x);
            a[x].v = y;
        }
        //        cout<<a[1].ch[0]<<" "<<a[1].ch[1]<<" "<<a[1].fa<<" "<<a[1].v<<" "<<a[1].s<<endl;
    }
    return 0;
}

魔法森林:

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;i++)
#define lv(i,a,n) for(register int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
#define min2(x,y) if(x>y)x=y;
const int N = 2e5 + 5;
const int P = 131072;
struct node
{
    int fa,ch[2],rev,v,mx;
}a[N];
int st[N],n,m;
struct edge
{
    int u,v,a,b;
    bool operator < (const edge &oth) const
    {
        return a < oth.a;
    }
    void getin()
    {
        read(u);read(v);
        read(a);read(b);
        u |= P;v |= P;
    }
}e[2 * N];
bool isroot(int x)
{
    return a[a[x].fa].ch[0] != x && a[a[x].fa].ch[1] != x;
}
void pushr(int x)
{
    swap(a[x].ch[0],a[x].ch[1]);
    a[x].rev ^= 1;
}
void push_down(int x)
{
    if(a[x].rev)
    {
//        if(a[a[x].ch[0]].rev) pushr(a[x].ch[0]);
//        if(a[a[x].ch[1]].rev) pushr(a[x].ch[1]);
        swap(a[x].ch[0],a[x].ch[1]);
        a[a[x].ch[0]].rev ^= 1;
        a[a[x].ch[1]].rev ^= 1;
        a[x].rev ^= 1;
    }
}
void push_up(int x)
{
    a[x].mx = x;
    if(e[a[x].mx].b < e[a[a[x].ch[0]].mx].b) a[x].mx = a[a[x].ch[0]].mx;
    if(e[a[x].mx].b < e[a[a[x].ch[1]].mx].b) a[x].mx = a[a[x].ch[1]].mx;
}
int iden(int x)
{
    return a[a[x].fa].ch[0] == x ? 0 : 1;
}
void connect(int x,int fa,int son)
{
    a[x].fa = fa;
    a[fa].ch[son] = x;
}
void rotate(int x)
{
    int y = a[x].fa;
    int mroot = a[y].fa;
    int mrootson = iden(y);
    int yson = iden(x);
    int b = a[x].ch[yson ^ 1];
    if(!isroot(y))
    {
        a[mroot].ch[mrootson] = x;
    }
    a[x].fa = mroot;
    connect(y,x,yson ^ 1);
    connect(b,y,yson);
    push_up(y);
//    update(x);
}
void splay(int x)
{
    int top = 0,i;
    st[++top] = x;
    for(i = x;!isroot(i);i = a[i].fa)
    {
        st[++top] = a[i].fa;
    }
    push_down(a[i].fa);
    for(int i = top;i;i--)
    {
        push_down(st[i]);
    }
    while(!isroot(x))
    {
        int y = a[x].fa;
        if(isroot(y)) rotate(x);
        else if(iden(x) == iden(y))
        {
            rotate(y);rotate(x);
        }
        else
        {
            rotate(x);rotate(x);
        }
    }
    push_up(x);
}
void access(int x)
{
    int t = 0;
    while(x)
    {
        splay(x);
        a[x].ch[1] = t;
        push_up(x);
        t = x;
        x = a[x].fa;
    }
}
void makeroot(int x)
{
    access(x);
    splay(x);
    a[x].rev ^= 1; 
}
int findroot(int x)
{
    access(x);
    splay(x);
    while(a[x].ch[0])
    x = a[x].ch[0];
    return x;
}
void link(int x)
{
    int y = e[x].u,z = e[x].v;
    makeroot(z);
    a[a[z].fa = x].fa = y;
//    a[x].fa = y;
}
void cut(int x)
{
    access(e[x].v);
    splay(x);
    a[x].ch[0] = a[x].ch[1] = a[a[x].ch[0]].fa = a[a[x].ch[1]].fa = 0;
    push_up(x);
}
int main()
{
//    freopen("2387.in","r",stdin);
    int ans = INF;
    read(n);read(m);
    duke(i,1,m)
    {
        e[i].getin();
    }
    sort(e + 1,e + m + 1);
    int y,z;
    duke(i,1,m)
    {
        if((y = e[i].u) == (z = e[i].v)) continue;
        makeroot(y);
        if(y != findroot(z)) link(i);
        else if(e[i].b < e[a[z].mx].b) 
        {
            cut(a[z].mx);
            link(i);
        }
        makeroot(1 | P);
        if((1 | P) == findroot(n | P))
        ans = min(ans,e[i].a + e[a[n | P].mx].b);
    }
    printf("%d\n",ans == INF ? -1 : ans);
    return 0;
}

弹飞绵羊:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<vector>
#include<complex>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
#define mp make_pair
#define cp complex<db>
#define enter puts("")
const long long INF = 1LL << 60;
const double eps = 1e-8;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
struct node
{
    int ch[2],siz,fa;
}a[1000005];
int n,m;
int iden(int x)
{
    return a[a[x].fa].ch[0] == x ? 0 : 1;
}
void connect(int x,int fa,int son)
{
    a[x].fa = fa;
    a[fa].ch[son] = x;
}
bool isroot(int x)
{
    return a[a[x].fa].ch[0] != x && a[a[x].fa].ch[1] != x;
}
void push_up(int x)
{
    a[x].siz = a[a[x].ch[0]].siz + a[a[x].ch[1]].siz + 1;
}
/*void pushr(int x)
{
    swap(a[x].ch[0],a[x].ch[1]);
    a[x].rev ^= 1;
}
void push_down(int x)
{
    if(a[x].rev)
    {
        if(a[x].ch[0]) pushr(a[x].ch[0]);
        if(a[x].ch[1]) pushr(a[x].ch[1]);
        a[x].rev ^= 1;
    }
}*/
void rotate(int x)
{
    int y = a[x].fa;
    int mroot = a[y].fa;
    int mrootson = iden(y);
    int yson =iden(x);
    int b = a[x].ch[yson ^ 1];
    if(!isroot(y))
    {
        a[mroot].ch[mrootson] = x;
    }
    a[x].fa = mroot;
    connect(b,y,yson);
    connect(y,x,yson ^ 1);
    push_up(y);
}
/*inline bool isroot(int x){
    return a[a[x].fa].ch[0]==x||a[a[x].fa].ch[1]==x;
}
void rotate(int x){
    int y=a[x].fa,z=a[y].fa,k=a[y].ch[1]==x,w=a[x].ch[!k];
    if(isroot(y))a[z].ch[a[z].ch[1]==y] = x;a[x].ch[!k]=y;a[y].ch[k]=w;
    if(w)a[w].fa=y;a[y].fa=x;a[x].fa=z;
    push_up(y);
}*/
void splay(int x)
{
    while(!isroot(x))
    {
        int y = a[x].fa;
        if(isroot(y)) rotate(x);
        else if(iden(x) == iden(y))
        {
            rotate(y);rotate(x);
        }
        else
        {
            rotate(x);rotate(x);
        }
    }
    push_up(x);
}
/*void splay(int x){
    int y,z;
    while(isroot(x)){
        y=a[x].fa;z=a[y].fa;
        cout<<x<<endl;
        if(isroot(y))
            rotate((a[y].ch[0]==x)^(a[z].ch[0]==y)?y:x);
        rotate(x);
    }
    push_up(x);
}*/
void access(int x)
{
    int t = 0;
    while(x)
    {
        splay(x);
        a[x].ch[1] = t;
        t = x;
        push_up(x);
        x = a[x].fa;
    }
}
int ch,j,k;
int main()
{
    // freopen("3203.in","r",stdin);
    read(n);
    duke(i,1,n)
    {
        a[i].siz = 1;
        read(k);
        if(i + k <= n)
        a[i].fa = i + k;
    }
    read(m);
    while(m--)
    {
        read(ch);
        if(ch == 1)
        {
            read(j);j++;
            access(j);splay(j);
            printf("%d\n",a[j].siz);
        }
        else
        {
            read(j);read(k); ++j;
            access(j);splay(j);
            a[j].ch[0] = a[a[j].ch[0]].fa = 0;
            if(j + k <= n) a[j].fa = j + k;
            push_up(j);
        }
    }
    return 0;
}
/*int main()
{
    freopen("3203.in","r",stdin);
    register char ch;
    int n,m,j,k;
    read(n);
    for(j=1;j<=n;++j){
        a[j].siz=1;
        read(k);
        if(j+k<=n)a[j].fa=j+k;//如果弹飞了就不连边
    }
    read(m);
    int op = 0;
    while(m--){
        read(op);
        if(op&1){
            read(j);++j;
            access(j);splay(j);//直接查询
            printf("%d\n",a[j].siz);
        }
        else{
            read(j);read(k);++j;
            access(j);splay(j);
            a[j].ch[0]=a[a[j].ch[0]].fa=0;//直接断边
            if(j+k<=n)a[j].fa=j+k;//直接连边
            push_
            up(j);
        }
    }
    return 0;
}*/

洞穴勘测:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;i++)
#define lv(i,a,n) for(register int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
struct node
{
    int fa,ch[2],rev;
}a[10005];
int n,m,st[10005];
bool isroot(int x)
{
    return a[a[x].fa].ch[0] != x && a[a[x].fa].ch[1] != x;
}
void push_down(int k)
{
    if(a[k].rev)
    {
        int l = a[k].ch[0];
        int r = a[k].ch[1];
        a[k].rev ^= 1;
        a[l].rev ^= 1;
        a[r].rev ^= 1;
        swap(a[k].ch[0],a[k].ch[1]);
    }
}
int iden(int x)
{
    return a[a[x].fa].ch[0] == x ? 0 : 1;
}
void connect(int x,int f,int son)
{
    a[x].fa = f;
    a[f].ch[son] = x;
}
void rotate(int x)
{
    int y = a[x].fa;
    int mroot = a[y].fa;
    int mrootson = iden(y);
    int yson = iden(x);
    int b = a[x].ch[yson ^ 1];
    if(!isroot(y))
    {
        a[mroot].ch[mrootson] = x;
    }
    a[x].fa = mroot;
    connect(b,y,yson);
    connect(y,x,yson ^ 1);
}
void splay(int x)
{
    int top = 0;
    st[++top] = x;
    for(int i = x;!isroot(i);i = a[i].fa)
    {
        st[++top] = a[i].fa;
        // cout<<"gg"<<endl;
    }
    // cout<<"out"<<endl;
    for(int i = top;i;i--)
    push_down(st[i]);
    while(!isroot(x))
    {
        int y = a[x].fa;
        if(isroot(y)) rotate(x);
        else if(iden(x) == iden(y))
        {
            rotate(y);rotate(x);
        }
        else
        {
            rotate(x);rotate(x);
        }
        // cout<<"233"<<endl;
    }
}
void access(int x)
{
    int t = 0;
    while(x)
    {
        splay(x);
        a[x].ch[1] = t;
        t = x;
        x = a[x].fa;
    }
}
void rever(int x)
{
    access(x);
    splay(x);
    a[x].rev ^= 1;
}
void link(int x,int y)
{
    rever(x);a[x].fa = y;
    splay(x);
    // cout<<x<<" "<<y<<endl;
}
void cut(int x,int y)
{
    rever(x);
    access(y);
    splay(y);
    a[y].ch[0] = a[x].fa = 0;
}
int find(int x)
{
//    cout<<x<<endl;
    access(x);//cout<<"yes"<<endl;
    splay(x);
    int y = x;
    //cout<<"!!!"<<y<<endl;
    while(a[y].ch[0])
    y = a[y].ch[0];
    // cout<<y<<endl;
    return y;
}
int main()
{
    // freopen("2147.in","r",stdin);
    char ch[10];
    int x,y;
    read(n);read(m);
    duke(i,1,m)
    {
        scanf("%s",ch);
        read(x);read(y);
        if(ch[0] == 'C') link(x,y);
        else if(ch[0] == 'D') cut(x,y);
        else
        {
            if(find(x) == find(y)) printf("Yes\n");
            else
            printf("No\n");
        }
    }
    return 0;
}

 

posted @ 2018-12-19 19:21  DukeLv  阅读(338)  评论(1编辑  收藏  举报