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;
}
原文地址:https://www.cnblogs.com/WuliWuliiii/p/14336611.html