bzoj 3223: Tyvj 1729 文艺平衡树

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,记得处理好标记下放。算是给自己留个splay模板吧

#include<cstdio>
#include<algorithm>
using namespace std;
struct tree
{
     int l,r;
     int ll,rr;
     int fa;
     int x;
     int turn;
}tr[100003];
int root,tot;
/*
inline void up(int p)
{
}
*/
inline void down(int p)
{
	 int p1=tr[p].l,p2=tr[p].r;
     if(tr[p].turn)
     {  
          tr[p1].turn^=1;
          tr[p2].turn^=1;
          swap(tr[p1].l,tr[p1].r);
          swap(tr[p2].l,tr[p2].r);
          swap(tr[p1].ll,tr[p1].rr);
          swap(tr[p2].ll,tr[p2].rr);
          tr[p].turn=0;  
     }  
}
inline void build(int &p,int l,int r)
{
     int mid=(l+r)/2;
     tot++;
     p=tot;
     tr[p].x=mid;
     if(l==r)
          return ;
     if(mid-l>0)
     {
          tr[p].ll=mid-l;
          build(tr[p].l,l,mid-1);
          tr[tr[p].l].fa=p;
     }
     if(r-mid>0)
     {
          tr[p].rr=r-mid;
          build(tr[p].r,mid+1,r);
		  tr[tr[p].r].fa=p; 
     }
     //up(p)
}
inline void zig(int p)
{
     int t=tr[p].l;
     tr[p].l=tr[t].r;
     tr[p].ll=tr[t].rr;
     tr[t].r=p;
     tr[t].rr+=tr[p].rr+1;
     tr[t].fa=tr[p].fa;
     tr[p].fa=t;
     tr[tr[p].l].fa=p;
     if(p==tr[tr[t].fa].l)
	      tr[tr[t].fa].l=t;
     else
	      tr[tr[t].fa].r=t;
     //up(p);
     //up(t);
}
inline void zag(int p)
{
     int t=tr[p].r;
     tr[p].r=tr[t].l;
     tr[p].rr=tr[t].ll;
     tr[t].l=p;
     tr[t].ll+=tr[p].ll+1;
     tr[t].fa=tr[p].fa;
     tr[p].fa=t;
     tr[tr[p].r].fa=p;
     if(p==tr[tr[t].fa].l)
	      tr[tr[t].fa].l=t;
     else
	      tr[tr[t].fa].r=t;
     //up(p);
     //up(t);
}
int q[1000001];
inline void splay(int x,int &p)
{
     int pt=0;
     int i;
     for(i=x;i!=0;i=tr[i].fa)
     {
          pt++;
          q[pt]=i;
     }
     while(pt>0)
     {
          down(q[pt]);
          pt--;
     }
     int fa=tr[p].fa;
     while(tr[x].fa!=fa)
     {
          int y=tr[x].fa,z=tr[y].fa;
          if(z==fa)
          {
               if(x==tr[y].l)
                    zig(y);
               else
                    zag(y);
          }
          else if(y==tr[z].l)
          {
               if(x==tr[y].l){zig(z);zig(y);}
               else{zag(y);zig(z);}
          }
          else if(y==tr[z].r)
          {
               if(x==tr[y].r){zag(z);zag(y);}
               else{zig(y);zag(z);}
          }
     }
     p=x;
}
inline int find(int p,int rank)
{
     down(p);
     if(tr[p].ll+1==rank)
          return p;
     if(tr[p].ll+1<rank)
          return find(tr[p].r,rank-tr[p].ll-1);
     else
          return find(tr[p].l,rank);
}
inline void turn(int s,int t)
{
     int u=find(root,s),v=find(root,t+2);
     splay(u,root);
     splay(v,tr[root].r);
     int p=tr[tr[root].r].l;
     tr[p].turn^=1;
     swap(tr[p].l,tr[p].r);
     swap(tr[p].ll,tr[p].rr);
}
int main()
{
     int n,m;
     scanf("%d%d",&n,&m);
     int i;
     build(root,0,n+1);
     int s,t;
     for(i=1;i<=m;i++)
     {
          scanf("%d%d",&s,&t);
          turn(s,t);
     }
     for(i=1;i<=n-1;i++)
     {
     	  int p=find(root,i+1);
          printf("%d ",tr[p].x);
     }
     int p=find(root,n+1);
     printf("%d ",tr[p].x);
     return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值