洛谷 P3391 【模板】文艺平衡树(Splay)

题目背景

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

题目描述

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

输入输出格式

输入格式:

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

接下来m行每行两个数 [l,r][l,r] 数据保证 1 leq l leq r leq n1lrn

输出格式:

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

输入输出样例

输入样例#1:
5 3
1 3
1 3
1 4
输出样例#1:
4 3 2 1 5

说明

n, m leq 100000n,m100000

 

splay区间操作

把l-1旋到根,r+1旋到右节点,打上flag标记。

屠龙宝刀点击就送

#include <algorithm>
#include <ctype.h>
#include <cstdio>
#define INF 0x7fffffff 
#define N 100010

using namespace std;
inline void read(int &x)
{
    x=0;bool f=0;
    register char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=1;
    for(; isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
    x=f?(~x)+1:x;
}
struct node
{
    int data,pos;
    bool operator<(node a)const
    {
        if(data==a.data) return pos<a.pos;
        return data<a.data;
    }
}d[N];
int data[N],flag[N],ch[N][2],fa[N],siz[N],root,n,m,cn,mn[N],pos[N];
inline int min(int a,int b) {return a>b?b:a;}
inline void pushup(int x)
{
    mn[x]=min(data[x],min(mn[ch[x][0]],mn[ch[x][1]]));
    if(mn[x]==data[x]) pos[x]=x;
    else if(mn[x]==mn[ch[x][0]]) pos[x]=pos[ch[x][0]];
    else pos[x]=pos[ch[x][1]];
    siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
inline void pushdown(int x)
{
    if(flag[x])
    {
        flag[x]=0;
        flag[ch[x][0]]^=1;
        swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
        flag[ch[x][1]]^=1;
        swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
    }
}
inline int son(int x) {return ch[fa[x]][1]==x;}
int getkth(int rt,int k)
{
    pushdown(rt);
    int l=ch[rt][0];
    if(siz[l]+1==k) return rt;
    if(k<siz[l]+1) return getkth(ch[rt][0],k);
    return getkth(ch[rt][1],k-(siz[l]+1));
}
inline void rotate(int x)
{
    int y=fa[x],z=fa[y],b=son(x),c=son(y),a=ch[x][!b];
    if(z) ch[z][c]=x;else root=x;fa[x]=z;
    if(a) fa[a]=y;ch[y][b]=a;
    ch[x][!b]=y;fa[y]=x;
    pushup(y);pushup(x);
}
void splay(int x,int i)
{
    while(fa[x]!=i)
    {
        int y=fa[x],z=fa[y];
        if(z==i) rotate(x);
        else 
        {
            pushdown(z);
            pushdown(y);
            pushdown(x);
            if(son(x)==son(y))
            {
                rotate(y);
                rotate(x);
            }
            else 
            {
                rotate(x);
                rotate(x);
            }
        }
    }
}
void reverse(int l,int r)
{
    int ll=getkth(root,l-1),rr=getkth(root,r+1);
    splay(ll,0);
    splay(rr,ll);
    int p=ch[rr][0];
    flag[p]^=1;
    swap(ch[p][0],ch[p][1]);
}
void dfs(int x)
{
    if(!x) return;
    pushdown(x);
    dfs(ch[x][0]);
    if(x>1&&x<n+2) printf("%d ",data[x]-1);
    dfs(ch[x][1]);
}
int main()
{
    read(n);
    read(m);
    for(int i=2;i<=n+1;i++)
    {
        data[i]=i-1;
        d[i].data=i-1;
        d[i].pos=i;
    }
    sort(d+2,d+2+n);
    for(int i=2;i<=n+1;i++) data[d[i].pos]=i;
    data[0]=data[1]=data[n+2]=INF;
    for(int i=0;i<=n+2;i++) mn[i]=INF;
    root=1;
    siz[0]=0;
    for(int i=1;i<=n+2;i++)
    {
        fa[i]=i-1;
        ch[i][1]=i+1;
    }
    ch[n+2][1]=0;
    for(int i=n+2;i>=1;i--) pushup(i);
    for(int l,r,i=1;i<=m;i++)
    {
        read(l);
        read(r);
        reverse(l+1,r+1);
    }
    dfs(root);
    return 0;
}
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
原文地址:https://www.cnblogs.com/ruojisun/p/7339567.html