3223: Tyvj 1729 文艺平衡树 —— splay区间翻转模板题

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

Input
第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n) m表示翻转操作次数
接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n

Output

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

Sample Input
5 3

1 3

1 3

1 4

Sample Output
4 3 2 1 5

HINT

N,M<=100000

随便找的

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define keytree ch[ch[root][1]][0]
#define L(x) ch[x][0]
#define R(x) ch[x][1]
#define N 300010
int ch[N][2],pre[N],cnt[N],size[N],val[N],small[N],rev[N],key[N];
int tot,root;
int a[N],n,m;
void newnode(int &u,int fa,int w,int KEY)
{
    u=++tot;
    ch[u][0]=ch[u][1]=rev[u]=0;
    pre[u]=fa;size[u]=1;
    val[u]=small[u]=w;
    key[u]=KEY;
}
void up(int u)
{
    size[u]=1+size[L(u)]+size[R(u)];
    small[u]=min(val[u],min(small[L(u)],small[R(u)]));
}
void down(int u)
{
    if(rev[u])
    {
        if(L(u))rev[L(u)]^=1;
        if(R(u))rev[R(u)]^=1;
        swap(L(u),R(u));
        rev[u]=0;
    }
}
void rotate(int u,int kind)//kind表示u在fa的哪一边
{
    int fa=pre[u];
    down(fa);down(u);
    ch[fa][kind]=ch[u][!kind];
    pre[ch[u][!kind]]=fa;
    if(pre[fa])ch[pre[fa]][ch[pre[fa]][1]==fa]=u;
    pre[u]=pre[fa];
    ch[u][!kind]=fa;
    pre[fa]=u;
    up(fa);up(u);
}
void splay(int u,int goal)
{
    int fa,kind;
    down(u);
    while(pre[u]!=goal)
    {
        if(pre[pre[u]]==goal)
        {
            down(pre[u]);down(u);
            rotate(u,R(pre[u])==u);
        }
        else
        {
            fa=pre[u];
            down(pre[u]);down(fa);down(u);
            kind=R(pre[fa])==fa;
            if(ch[fa][kind]!=u)//不在同一侧
            {
                rotate(u,!kind);
                rotate(u,kind);
            }
            else
            {
                rotate(fa,kind);
                rotate(u,kind);
            }
        }
    }
    up(u);
    if(goal==0)root=u;
}
int getkth(int u,int k)//第k个键值的点的编号
{
    down(u);
    int s=size[L(u)]+1;
    if(s==k) return u;
    if(s>k) return getkth(L(u),k);
    else return getkth(R(u),k-s);
}
int find(int u,int x)//查找键值为x的点的编号
{                    // 有反转标记时不可用
    down(u);
    if(key[u]==x)return u;
    if(key[u]>x)
    {
        if(!L(u))return -1;
        return find(L(u),x);
    }
    if(key[u]<x)
    {
        if(!R(u))return -1;
        return find(R(u),x);
    }
}
int getpre(int u)
{
    down(u);u=L(u);down(u);
    while(R(u))
    {
        u=R(u);
        down(u);
    }
    return u;
}
int getnext(int u)
{
    down(u);u=R(u);down(u);
    while(L(u))
    {
        u=L(u);
        down(u);
    }
    return u;
}
void del(int x)//删除编号为x的节点
{
    if(cnt[x]>1)
    {
        cnt[x]--;
        return ;
    }
    splay(x,0);
    if(L(root))
    {
        int p=getpre(x);
        splay(p,root);
        R(p)=R(root);
        pre[R(root)]=p;
        root=p;
        pre[p]=0;
        up(root);
    }
    else
    {
        root=R(root);
        pre[root]=0;
    }
}
void build(int &u,int l,int r,int fa)//按pos为键值
{                        //val为数的大小 a存数的大小
    if(l>r)return ;
    int mid=(l+r)>>1;
    newnode(u,fa,a[mid],mid);
    build(L(u),l,mid-1,u);
    build(R(u),mid+1,r,u);
    up(u);
}
void init()
{
    root=tot=0;
    L(root)=R(root)=pre[root]=size[root]=rev[root]=0;
    val[root]=small[root]=N;
    newnode(root,0,N,0);
    newnode(R(root),root,N,N);
    build(keytree,1,n,R(root));
    up(R(root));
    up(root);
}
int getmin(int u,int x)//得到最小值的相对位置
{
    down(u);
    if(val[u]==x) return 1+size[L(u)];
    if(small[L(u)]==x) return getmin(L(u),x);
    if(small[R(u)]==x) return size[L(u)]+1+getmin(R(u),x);
}
//--------------------------------------------------基本操作
int sum;
void dfs(int root)
{
    if(root==0)
        return ;
    down(root);
    dfs(ch[root][0]);
    if(key[root]!=0&&key[root]!=N)
    {
        sum++;
        printf("%d%c",key[root],sum==n?'\n':' ');
    }
    dfs(ch[root][1]);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        a[i]=n-i+1;
    init();
    int l,r;
    while(m--)
    {
        scanf("%d%d",&l,&r);
        int pos=getkth(root,l);
        splay(pos,0);
        pos=getkth(root,r+2);
        splay(pos,root);
        rev[keytree]^=1;
    }
    dfs(root);
}

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/82022991
今日推荐