zoukankan      html  css  js  c++  java
  • LCT

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 100010;
    
    int n, m;
    struct Node
    {
        int s[2], p, v;
        int sum, rev;
    }tr[N];
    int stk[N];
    
    void pushrev(int x)
    {
        swap(tr[x].s[0], tr[x].s[1]);
        tr[x].rev ^= 1;
    }
    
    void pushup(int x)
    {
        tr[x].sum = tr[tr[x].s[0]].sum ^ tr[x].v ^ tr[tr[x].s[1]].sum;
    }
    
    void pushdown(int x)
    {
        if (tr[x].rev)
        {
            pushrev(tr[x].s[0]), pushrev(tr[x].s[1]);
            tr[x].rev = 0;
        }
    }
    
    bool isroot(int x)
    {
        return tr[tr[x].p].s[0] != x && tr[tr[x].p].s[1] != x;
    }
    
    void rotate(int x)
    {
        int y = tr[x].p, z = tr[y].p;
        int k = tr[y].s[1] == x;
        if (!isroot(y)) tr[z].s[tr[z].s[1] == y] = x;
        tr[x].p = z;
        tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y;
        tr[x].s[k ^ 1] = y, tr[y].p = x;
        pushup(y), pushup(x);
    }
    
    void splay(int x)
    {
        int top = 0, r = x;
        stk[ ++ top] = r;
        while (!isroot(r)) stk[ ++ top] = r = tr[r].p;
        while (top) pushdown(stk[top -- ]);
        while (!isroot(x))
        {
            int y = tr[x].p, z = tr[y].p;
            if (!isroot(y))
                if ((tr[y].s[1] == x) ^ (tr[z].s[1] == y)) rotate(x);
                else rotate(y);
            rotate(x);
        }
    }
    
    void access(int x)  // 建立一条从根到x的路径,同时将x变成splay的根节点
    {
        int z = x;
        for (int y = 0; x; y = x, x = tr[x].p)
        {
            splay(x);
            tr[x].s[1] = y, pushup(x);
        }
        splay(z);
    }
    
    void makeroot(int x)  // 将x变成原树的根节点
    {
        access(x);
        pushrev(x);
    }
    
    int findroot(int x)  // 找到x所在原树的根节点, 再将原树的根节点旋转到splay的根节点
    {
        access(x);
        while (tr[x].s[0]) pushdown(x), x = tr[x].s[0];
        splay(x);
        return x;
    }
    
    void split(int x, int y)  // 给x和y之间的路径建立一个splay,其根节点是y
    {
        makeroot(x);
        access(y);
    }
    
    void link(int x, int y)  // 如果x和y不连通,则加入一条x和y之间的边
    {
        makeroot(x);
        if (findroot(y) != x) tr[x].p = y;
    }
    
    void cut(int x, int y)  // 如果x和y之间存在边,则删除该边
    {
        makeroot(x);
        if (findroot(y) == x && tr[y].p == x && !tr[y].s[0])
        {
            tr[x].s[1] = tr[y].p = 0;
            pushup(x);
        }
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i ++ ) scanf("%d", &tr[i].v);
        while (m -- )
        {
            int t, x, y;
            scanf("%d%d%d", &t, &x, &y);
            if (t == 0)
            {
                split(x, y);
                printf("%d
    ", tr[y].sum);
            }
            else if (t == 1) link(x, y);
            else if (t == 2) cut(x, y);
            else
            {
                splay(x);
                tr[x].v = y;
                pushup(x);
            }
        }
    
        return 0;
    }

    用法:

    1 可删除边的并查集 

    2 利用split(x,y)维护

  • 相关阅读:
    轻松自动化---selenium-webdriver(python) (八)
    Ubuntu 18.04 LTS 启用 WakeOnLAN
    lower_bound 和 upper_bound
    [LeetCode 201.] Bitwise AND of Numbers Range
    [LeetCode 162.] Find Peak Element
    [LeetCode 33. 81. 153. 154.] 旋转数组中的二分查找
    C++ unordered_map 的一个疑问
    [LintCode 386.] 最多有k个不同字符的最长子字符串
    [LintCode 550.] 最常使用的K个单词II
    [LintCode 1029.] 寻找最便宜的航行旅途(最多经过k个中转站)
  • 原文地址:https://www.cnblogs.com/cyq123/p/13994590.html
Copyright © 2011-2022 走看看