BZOJ3223文艺平衡树

3223: Tyvj 1729 文艺平衡树
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 2705 Solved: 1529
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
平衡树
splay模板题。。
终于打了一次splay。。
附上本蒟蒻的代码:

#include<cstdio>
#include<iostream>
using namespace std;
#define MAXN 100001
int n,m,sz,rt,father[MAXN],c[MAXN][2],id[MAXN],size[MAXN];
bool rev[MAXN];

int read()
{
    int w=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9')
      {
        if (ch=='-') f=-1;
        ch=getchar();
      }
    while (ch>='0' && ch<='9')
      w=w*10+ch-'0',ch=getchar();
    return w*f;
}

void update(int s)
{
    int l=c[s][0],r=c[s][1];
    size[s]=size[l]+size[r]+1;
}

void pushdown(int s)
{
    int l=c[s][0],r=c[s][1];
    if (rev[s])
      {
        swap(c[s][0],c[s][1]);
        rev[l]^=1,rev[r]^=1;
        rev[s]=0;
      }
}

void rotate(int x,int &s)
{
    int y=father[x],z=father[y],l,r;
    if (c[y][0]==x) l=0;
    else l=1;
    r=l^1;
    if (y==s) s=x;
    else 
      if (c[z][0]==y) 
        c[z][0]=x;
      else 
        c[z][1]=x;
    father[x]=z,father[y]=x,father[c[x][r]]=y;
    c[y][l]=c[x][r],c[x][r]=y;
    update(y),update(x);
}

void splay(int x,int &s)
{
    int y,z;
    while (x!=s)
      {
        y=father[x],z=father[y];
        if (y!=s)
          if (c[y][0]==x^c[z][0]==y) 
            rotate(x,s);
          else 
            rotate(y,s);
        rotate(x,s);
      }
}

int find(int s,int rank)
{
    pushdown(s);
    int l=c[s][0],r=c[s][1];
    if (size[l]+1==rank) 
      return s;
    else 
      if (size[l]>=rank) 
        return find(l,rank);
      else 
        return find(r,rank-size[l]-1);
}

void rever(int l,int r)
{
    int x=find(rt,l),y=find(rt,r+2);
    splay(x,rt);splay(y,c[x][1]);
    int z=c[y][0];
    rev[z]^=1;
}

void build(int l,int r,int f)
{
    if (l>r) return;
    int now=id[l],last=id[f];
    if (l==r)
      {
        father[now]=last,size[now]=1;
        if (l<f) c[last][0]=now;
        else c[last][1]=now;
        return;
      }
    int mid=(l+r)>>1;
    now=id[mid];
    build(l,mid-1,mid);build(mid+1,r,mid);
    father[now]=last,update(mid);
    if (mid<f) c[last][0]=now;
    else c[last][1]=now;
}

int main()
{
    int i,l,r;
    n=read(),m=read();
    for (i=1;i<=n+2;i++)
      id[i]=++sz;
    build(1,n+2,0);
    rt=(n+3)>>1;
    for (i=1;i<=m;i++)
      {
        l=read(),r=read();
        rever(l,r);
      }
    for (i=2;i<=n+1;i++)
      printf("%d ",find(rt,i)-1);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值