[BZOJ 3223]Tyvj 1729 文艺平衡树(Splay)

本文介绍了一种用于维护有序数列并支持区间翻转操作的数据结构实现,通过使用树状结构进行高效的区间翻转和查询操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

Solution


发现自己数据结构超·级·弱
存代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define MAXN 100005
using namespace std;
int n,m,siz=0,root;
struct Node{
    int key,ch[2],siz,father,rev;
}t[MAXN];
int Read()
{
    int f=1,x=0;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';c=getchar();
    }
    return x*f;
}
void Update(int x)
{
    t[x].siz=t[t[x].ch[0]].siz+t[t[x].ch[1]].siz+1;
}
void Pushdown(int x)
{
    if(x&&t[x].rev)
    {
        t[x].rev=0;
        t[t[x].ch[0]].rev^=1;
        t[t[x].ch[1]].rev^=1;
        swap(t[x].ch[0],t[x].ch[1]);
    }
}
void Rotate(int x,int &k)
{
    int y=t[x].father;
    int z=t[y].father;
    int p=(x==t[y].ch[0])?0:1;
    if(y==k)k=x;
    else{
        if(t[z].ch[0]==y)t[z].ch[0]=x;
        else t[z].ch[1]=x;
    }
    t[x].father=z;
    t[y].ch[p]=t[x].ch[p^1];
    t[t[x].ch[p^1]].father=y;
    t[x].ch[p^1]=y;
    t[y].father=x;
    Update(x),Update(y);
}
void Splay(int x,int &k)
{
    while(x!=k)
    {
        int y=t[x].father;
        int z=t[y].father;
        if(y!=k)
        {
            if((x==t[y].ch[0])^(y==t[z].ch[0]))
            Rotate(x,k);
            else Rotate(y,k);
        }
        Rotate(x,k);
    }
}
int Build(int l,int r,int f)
{
    if(l>r)return 0;
    int mid,now;
    mid=(l+r)/2;
    siz++,now=siz;
    t[now].father=f,t[now].key=mid;
    t[now].ch[0]=Build(l,mid-1,now);
    t[now].ch[1]=Build(mid+1,r,now);
    Update(now);
    return now;
}
int Find(int x,int k)
{
    if(!k)return 0;
    Pushdown(k);
    if(x<=t[t[k].ch[0]].siz)Find(x,t[k].ch[0]);
    else if(x>t[t[k].ch[0]].siz+1)
    Find(x-t[t[k].ch[0]].siz-1,t[k].ch[1]);
    else return k;
}
void Print(int x)
{
    if(!x)return;
    Pushdown(x);
    Print(t[x].ch[0]);
    if(t[x].key!=1&&t[x].key!=n+2)
    printf("%d ",t[x].key-1);
    Print(t[x].ch[1]);
}
int main()
{
    n=Read();m=Read();
    root=Build(1,n+2,0);
    for(int i=1;i<=m;i++)
    {
        int l,r;
        l=Read();r=Read();
        int x=Find(l,root);
        int y=Find(r+2,root);
        Splay(x,root);Splay(y,t[root].ch[1]);
        root=x;
        t[t[t[root].ch[1]].ch[0]].rev^=1;
    }
    Print(root);
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值