【模板】Splay(luogu)

Background

这是一道经典的\(\text Splay\)模板题——文艺平衡树。

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是\(5 4 3 2 1\),翻转区间是\([2,4]\)的话,结果是\(5 2 3 4 1\)

Input

第一行为\(n,m\) \(n\)表示初始序列有\(n\)个数,这个序列依次是 \((1,2, \cdots n-1,n)\) \(m\)表示翻转操作次数

接下来\(m\)行每行两个数 \([l,r]\) 数据保证 \(1 \leq l \leq r \leq n\)

Output

输出一行\(n\)个数字,表示原始序列经过\(m\)次变换后的结果

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#define lson(x) son[x][0]
#define rson(x) son[x][1]
using namespace std;
int n,m,root,siz[200010],fa[200010],son[200010][2],tag[200010];
void updata(int u)
{
    siz[u]=siz[lson(u)]+siz[rson(u)]+1;
}
void down(int u)
{
    if (tag[u])
    {
        swap(lson(u),rson(u));
        tag[u]^=1;tag[lson(u)]^=1;tag[rson(u)]^=1;
    }
}
void build(int l,int r,int f)
{
    if (l>r) return;
    if (l==r)
    {
        fa[l]=f,siz[l]=1;
        son[f][l>f]=l;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid-1,mid),build(mid+1,r,mid);
    son[f][mid>f]=mid;fa[mid]=f;
    updata(mid);
}
int find(int rt,int k)
{
    down(rt);
    if (siz[lson(rt)]+1==k) return rt;
    if (siz[lson(rt)]>=k) return find(lson(rt),k);
    else return find(rson(rt),k-siz[lson(rt)]-1);
}
void rotate(int x,int &rt)
{
    int y=fa[x],z=fa[y],t=(rson(y)==x);
    if (y==rt) rt=x; else son[z][rson(z)==y]=x;
    fa[x]=z,fa[y]=x,fa[son[x][t^1]]=y;
    son[y][t]=son[x][t^1];son[x][t^1]=y;
    updata(y);updata(x);
}
void splay(int x,int &rt)
{
    while (x!=rt)
    {
        int y=fa[x],z=fa[y];
        if (y!=rt)
            if (lson(z)==y ^ lson(y)==x) rotate(x,root);
            else rotate(y,root);
        rotate(x,root);
    }
}
void rever(int l,int r)
{
    l=find(root,l);r=find(root,r+2);
    splay(l,root),splay(r,rson(root));
    tag[lson(rson(root))]^=1;
}
int main()
{
    scanf("%d%d",&n,&m);
    root=(n+3)>>1;
    build(1,n+2,0);
    while (m--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        rever(l,r);
    }
    for (int i=2;i<=n+1;i++)
        printf("%d ",find(root,i)-1);
    return 0;
}
上一篇:Count on a tree SPOJ - COT


下一篇:UOJ #56.线段树区间加和乘