华师一附中OI组

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1067|回复: 5
打印 上一主题 下一主题

P3391 【模板】文艺平衡树

[复制链接]

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
跳转到指定楼层
楼主
发表于 2020-4-25 12:16:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
https://www.luogu.com.cn/problem/P3391

题目描述
您需要写一种数据结构(可参考题目标题),来维护一个有序数列。

其中需要提供以下操作:翻转一个区间,例如原有序序列是 5 4 3 2 1,翻转区间是 [2,4] 的话,结果是 5 2 3 4 1。

输入格式
第一行两个正整数 n,m,表示序列长度与操作个数。序列中第 i 项初始为 i。
接下来 m 行,每行两个正整数 l,r,表示翻转的区间。

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

输入输出样例
输入 #1复制
5 3
1 3
1 3
1 4
输出 #1复制
4 3 2 1 5
说明/提示
【数据范围】
对于100% 的数据,1≤n,m≤100000,1≤l≤r≤n。
回复

使用道具 举报

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
沙发
 楼主| 发表于 2020-4-25 12:16:54 | 只看该作者
简易SPLAY裸体,作为SPLAY的入门很好!
回复 支持 反对

使用道具 举报

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
板凳
 楼主| 发表于 2020-4-25 12:21:08 | 只看该作者
SPLAY用于序列操作的
一般加上首尾两个假节点,这样旋转时候
回复 支持 反对

使用道具 举报

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
地板
 楼主| 发表于 2020-4-25 12:21:11 | 只看该作者
SPLAY用于序列操作的
一般加上首尾两个假节点,这样旋转时候
回复 支持 反对

使用道具 举报

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
5#
 楼主| 发表于 2020-4-25 12:21:24 | 只看该作者
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int inf=0X3FFFFFFF;
  4. const int N=100100;
  5. struct node
  6. {
  7.         int val,fa,s[2],sz,rev;
  8. } a[N];
  9. int n, tot, root;
  10. void ArrayPr()   
  11. {
  12.         cout<<endl<<"  i ";
  13.         for (int i=1; i<=tot; i++) cout<<setw(3)<<i;
  14.         cout<<endl<<"val ";
  15.         for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].val;
  16.         cout<<endl<<" s0 ";
  17.         for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].s[0];
  18.         cout<<endl<<" s1 ";
  19.         for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].s[1];
  20.         cout<<endl<<" fa ";
  21.         for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].fa;
  22.         cout<<endl<<" sz ";
  23.         for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].sz;
  24.         cout<<endl<<"rev ";
  25.         for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].rev;
  26.         cout<<endl;
  27. }
  28. void pushdown(int rt)
  29. {
  30.         if (rt==0) return ;
  31.         int R=a[rt].rev;
  32.         int l=a[rt].s[0], r=a[rt].s[1];
  33.         if (R>0)  
  34.                 {
  35.                         a[rt].s[0]=r,a[rt].s[1]=l;
  36.                         a[rt].rev=0;
  37.                         if (l>0)a[l].rev^=1;
  38.                         if (r>0)a[r].rev^=1;
  39.                 }
  40. }
  41. void pushup(int rt)
  42. {
  43.         int l=a[rt].s[0], r=a[rt].s[1];
  44.         a[rt].sz=a[l].sz+a[r].sz+1;
  45. }
  46. void BSTPr(int rt)   
  47. {
  48.         if (rt>0)
  49.                 {
  50.                         BSTPr(a[rt].s[0]);
  51.                         cout<<a[rt].val<<' ';
  52.                         BSTPr(a[rt].s[1]);
  53.                 }
  54. }
  55. int Son(int x)
  56. {
  57.         int y=a[x].fa;
  58.         return  a[y].s[1]==x;
  59. }
  60. void R(int x)
  61. {
  62.         int y=a[x].fa;
  63.         int z=a[y].fa;
  64.         pushdown(y),pushdown(x);///下传
  65.         int k=Son(x);
  66.         int v=a[x].s[k^1];

  67.         a[y].s[k]=v,a[v].fa=y;///v挂在y下
  68.         a[z].s[Son(y)]=x,a[x].fa=z;///x挂在z下
  69.         a[x].s[k^1]=y,a[y].fa=x;///y挂在x下
  70.         pushup(y),pushup(x);///上传
  71. }
  72. inline void Splay(int x,int rt=root)  
  73. {
  74.         rt=a[rt].fa;
  75.         int y,z;

  76.         while(a[x].fa!=rt)  
  77.                 {
  78.                         y=a[x].fa,z=a[y].fa;;
  79.                         if(z!=rt)
  80.                                 if(Son(x)==Son(y))R(y);
  81.                                 else R(x);
  82.                         R(x);
  83.                 }
  84.         if(rt==0)root=x;
  85. }
  86. int Getkth(int rt,int k) ///第k个的数的位置
  87. {
  88.         pushdown(rt);
  89.         int l=a[a[rt].s[0]].sz;  /// RT的左儿子下的个数
  90.         if(l+1==k) return rt;
  91.         if(l+1>k) return Getkth(a[rt].s[0], k); ///左儿子里去找
  92.         if(l+1<k) return Getkth(a[rt].s[1], k-(l+1));
  93. }
  94. int Build(int l,int r)
  95. {
  96.         if (l>r) return 0;
  97.         if (l==r)
  98.                 {
  99.                         a[l].val=l-1;
  100.                         a[l].sz=1;
  101.                         return  l;
  102.                 }
  103.         int m=(l+r)/2;
  104.         int L=a[m].s[0]=Build(l,m-1);
  105.         int R=a[m].s[1]=Build(m+1,r);
  106.         a[m].sz=r-l+1;
  107.         a[m].val=m-1;
  108.         a[L].fa=a[R].fa=m;
  109.         return m;
  110. }
  111. void Get(int x,int y) ///把 第x个转到根,y转到x的右子树
  112. {
  113.         int l=Getkth(root,x);
  114.         int r=Getkth(root,y);
  115.         Splay(l,root);
  116.         Splay(r,a[root].s[1]);
  117. }
  118. int main()
  119. {
  120.         int m,x,opt,L,R,V;
  121.         cin>>n>>m;
  122. ///初始建树
  123.         tot=n+2;
  124.         root=Build(1,tot);
  125.         while(m--)
  126.                 {
  127.                         cin>>L>>R;
  128.                         Get(L,R+2);
  129.                         int t=a[root].s[1];
  130.                         t=a[t].s[0];
  131.                         a[t].rev^=1;
  132.                 }
  133.         Get(1,n+2);
  134.         int t=a[root].s[1];
  135.         t=a[t].s[0];
  136.         BSTPr(t);
  137.         return 0;
  138. }
  139. /*
  140. 5 3
  141. 1 3
  142. 1 3
  143. 1 4
  144. */
复制代码
回复 支持 反对

使用道具 举报

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
6#
 楼主| 发表于 2020-5-6 11:17:21 | 只看该作者
DZY同学提醒:我的那个BSTPr里面少写了一句pushdown(rt)!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|服务支持:DZ动力|华师一附中OI组  

GMT+8, 2024-12-25 15:03 , Processed in 0.104569 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表