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

3223: Tyvj 1729 文艺平衡树

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 3321   Solved: 1887
[ Submit][ Status][ Discuss]

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

Source

[ Submit][ Status][ Discuss]

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
int root,sz,n,m;
int ch[100010][5],f[100010],size[100010],key[100010],a[100010],delta[100010];
void swap(int &x,int &y)
{
    int t;
    t=x;  x=y;  y=t;
}
void updata(int x)
{
    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
int get(int x)
{
    return ch[f[x]][1]==x;
}
void pushdown(int x)
{
    if (!x) return;
    if (!delta[x]) return;
    delta[ch[x][0]]^=1;
    delta[ch[x][1]]^=1;
    swap(ch[x][0],ch[x][1]);
    delta[x]=0;
}
int build (int l,int r,int fa)
{
    if (l>r) return 0;
    int mid=(l+r)>>1;
    int now=++sz;
    ch[now][0]=build(l,mid-1,now);
    ch[now][1]=build(mid+1,r,now);
    f[now]=fa; delta[now]=0;
    key[now]=a[mid];size[now]=size[ch[now][1]]+size[ch[now][0]]+1;
    return now;
} 
int find(int x)
{
    int now=root;
    while (true)
     {
        pushdown(now);
        if (x<=size[ch[now][0]])
         now=ch[now][0];
        else
         {
            x-=(size[ch[now][0]]+1);
            if (x==0)  return now;
            now=ch[now][1];
         }
     }
    return -1;
}
void rotate(int x)
{
  pushdown(f[x]); pushdown(x);
  int fa=f[x],oldfa=f[fa],which=get(x);
  ch[fa][which]=ch[x][which^1];  f[ch[x][which^1]]=fa;
  ch[x][which^1]=fa; f[fa]=x;
  f[x]=oldfa;
  if (oldfa)
   ch[oldfa][ch[oldfa][1]==fa]=x;
  updata(x); updata(fa);
}
void splay (int x,int l)
{
    pushdown(x);
    for (int fa;(fa=f[x])!=l;rotate(x))
     if (f[fa]!=l)
     rotate((get(fa)==get(x))?fa:x);
    if (l==0)  root=x;
}
void print(int now)
{
    pushdown(now);
    if (ch[now][0]) print(ch[now][0]);
    if (key[now]!=1000000000&&key[now]!=-1000000000)
     printf("%d ",key[now]);
    if (ch[now][1]) print(ch[now][1]); 
}
int main()
{
    scanf("%d%d",&n,&m);
    a[1]=-1000000000; a[n+2]=1000000000;
    for (int i=1;i<=n;i++)
     a[i+1]=i;
    root=build(1,n+2,0);
    for (int i=1;i<=m;i++)
     {
        int x,y;
        scanf("%d%d",&x,&y);
        int aa=find(x);
        int bb=find(y+2);
        splay(aa,0);
        splay(bb,aa);
        delta[ch[ch[root][1]][0]]^=1;
     }
    print(root);
    printf("\n"); 
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值