zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ",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
    ",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
    ",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
    ");
                else
                printf("No
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    SVN常用命令
    在windows下Oracle10g中创建数据库(一)
    PowerDesigner12.5 常用功能设置
    Windows下oracle xe 10g 手工创建数据库(二)
    Linux环境手动创建oracle10g数据库实践
    SQLSERVER数据库 'XX' 的事务日志已满。若要查明无法重用日志中的空间的原因,请参......
    SP中执行动态组串的sql
    手机号码吉凶测试原理计算公式
    SQL 2005 中 ROW_NUMBER 用法
    IIS 问题汇总
  • 原文地址:https://www.cnblogs.com/DukeLv/p/10145345.html
Copyright © 2011-2022 走看看