• Permutation Transformer【Splay】


      题意:有N个点,初始从1至N排列,现在我们对数轴上第l到第r区间内的所有的点进行翻转操作,问经过M次操作之后,数轴上的数的排列情况。

      很明显的,我们可以发现,这是一个Splay的操作,但是只有N个元素显得比较的麻烦了(细节+++),于是,我给首尾各加一个值,现在初始数轴变成了(1~N+2)。那么,当我们要把[L,R]区间拉出来的时候,实际上就是将(L)这个点拉成根节点,然后将(R+2)这个位置上的点拉到(L)的下面,那么(R+2)的左子树就是(L+1~R+1)的区间了,也正是对应我们的操作的([l,r])区间的。

      然后,这里有需要注意的地方,我们在进行Splay的时候,切记要先进行pushdown,先从将根到目前操作节点的lazy都pushdown了,不然有可能当我们将其中一个节点操作的时候,拉出子树的时候,还没有继承祖先节点的信息,容易造成数据缺失。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <limits>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #include <bitset>
    #include <unordered_map>
    #include <unordered_set>
    #define lowbit(x) ( x&(-x) )
    #define pi 3.141592653589793
    #define e 2.718281828459045
    #define INF 0x3f3f3f3f
    #define HalF (l + r)>>1
    #define lsn rt<<1
    #define rsn rt<<1|1
    #define Lson lsn, l, mid
    #define Rson rsn, mid+1, r
    #define QL Lson, ql, qr
    #define QR Rson, ql, qr
    #define myself rt, l, r
    #define pii pair<int, int>
    #define MP(a, b) make_pair(a, b)
    using namespace std;
    typedef unsigned long long ull;
    typedef unsigned int uit;
    typedef long long ll;
    const int maxN = 1e5 + 7;
    int N, M, root;
    bool rr[maxN] = {0};
    struct node
    {
        int ff, ch[2], siz;
        node() { ff = ch[0] = ch[1] = 0; siz = 0; }
        void init(int fa)
        {
            ff = fa;
            ch[0] = ch[1] = 0;
            siz = 1;
        }
    } t[maxN];
    void pushup(int x)
    {
        t[x].siz = 1;
        if(t[x].ch[0]) t[x].siz += t[t[x].ch[0]].siz;
        if(t[x].ch[1]) t[x].siz += t[t[x].ch[1]].siz;
    }
    void pushdown(int x)
    {
        if(rr[x])
        {
            rr[t[x].ch[0]] ^= 1;
            rr[t[x].ch[1]] ^= 1;
            swap(t[x].ch[0], t[x].ch[1]);
            rr[x] = 0;
        }
    }
    void Rotate(int x)
    {
        int y = t[x].ff, z = t[y].ff;
        int k = t[y].ch[1] == x;
        t[z].ch[t[z].ch[1] == y] = x;
        t[x].ff = z;
        t[y].ch[k] = t[x].ch[k ^ 1];
        t[t[x].ch[k ^ 1]].ff = y;
        t[x].ch[k ^ 1] = y;
        t[y].ff = x;
        pushup(y);
        pushup(x);
    }
    int Stap[maxN], Stop;
    void Splay(int x, int goal)
    {
        Stop = 0;
        int y = x, z;
        while(y) { Stap[++ Stop] = y; y = t[y].ff; }
        while(Stop) pushdown(Stap[Stop --]);
        while(t[x].ff != goal)
        {
            y = t[x].ff; z = t[y].ff;
            if(z != goal) (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? Rotate(x) : Rotate(y);
            Rotate(x);
        }
        if(!goal) root = x;
    }
    int build(int fa, int l, int r)
    {
        if(l > r) return 0;
        int mid = HalF;
        t[mid].init(fa);
        t[mid].ch[0] = build(mid, l, mid - 1);
        t[mid].ch[1] = build(mid, mid + 1, r);
        pushup(mid);
        return mid;
    }
    int kth(int k)
    {
        int u = root;
        if(t[u].siz < k) return 0;
        while(true)
        {
            pushdown(u);
            int v = t[u].ch[0];
            if(k > t[v].siz + 1)
            {
                k -= t[v].siz + 1;
                u = t[u].ch[1];
            }
            else
            {
                if(t[v].siz >= k) u = v;
                else return u;
            }
        }
    }
    void change(int l, int r)
    {
        int len = r - l + 1;
        int x = kth(l), y = kth(r + 2);
        Splay(x, 0);
        Splay(y, x);
        int u = t[y].ch[0];
        t[y].ch[0] = 0;
        t[u].ff = 0;
        pushup(y);
        pushup(x);
        
        rr[u] ^= 1;
        
        x = kth(N - len + 1);
        Splay(x, 0);
        y = t[x].ch[1];
        t[y].ch[0] = u;
        t[u].ff = y;
        pushup(y);
        pushup(x);
    }
    int ans[maxN], tot;
    void query(int x)
    {
        pushdown(x);
        if(t[x].ch[0]) query(t[x].ch[0]);
        if(x >= 2 && x <= N + 1) ans[++ tot] = x - 1;
        if(t[x].ch[1]) query(t[x].ch[1]);
    }
    void Prit()
    {
        query(root);
        for(int i = 1; i <= N; i ++) printf("%d
    ", ans[i]);
        tot = 0;
    }
    int main()
    {
        scanf("%d%d", &N, &M);
        root = build(0, 1, N + 2);
        for(int i = 1, l, r; i <= M; i ++)
        {
            scanf("%d%d", &l, &r);
            change(l, r);
        }
        Prit();
        return 0;
    }
  • 相关阅读:
    加密API实现与测试
    使用GO操作MongoDB
    go mongodb Pipeline 聚合查询格式
    [ZJOI 2022] 众数
    Generators All in One
    [Contest on 2022.5.27] 我还是一道题都不会做
    [干饭现场] 多项式全家桶
    [题目小结] 线性姬
    [Contest on 2022.5.31] 在 5 月 31 日的考试
    CodeForces 917D Stranger Trees
  • 原文地址:https://www.cnblogs.com/WuliWuliiii/p/14336611.html
Copyright © 2020-2023  润新知