splay 文艺平衡树 (数据结构)

题目大意:略

splay维护区间翻转裸题,为了减少不必要的麻烦,多插入两个点,分别是0和n+1

每次找区间的第K个值,就在splay上二分即可

顺便学了一下splay的完美建树,而且splay有一些小函数可以宏定义或者用inline,跑得飞快

最后跑一遍中序遍历即可

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #define N 100100
  5 #define il inline
  6 #define ll long long
  7 #define root d[0].ch[1]
  8 #define con(x,ff,p) d[x].fa=ff,d[ff].ch[p]=x
  9 #define idf(x) d[d[x].fa].ch[0]==x?0:1
 10 #define lb(x) (x&(-x))
 11 using namespace std;
 12
 13 int n,m,cnt;
 14 struct SPLAY{
 15     int fa,ch[2],id,sum,mrk;
 16 }d[N<<1];
 17 il void pushup(int x) {d[x].sum=d[d[x].ch[0]].sum+d[d[x].ch[1]].sum+1;}
 18 il void pushdown(int x)
 19 {
 20     if(!d[x].mrk) return;
 21     swap(d[x].ch[0],d[x].ch[1]);
 22     d[x].mrk=0;
 23     d[d[x].ch[0]].mrk^=1;
 24     d[d[x].ch[1]].mrk^=1;
 25 }
 26 il void rot(int x)
 27 {
 28     int y=d[x].fa;int ff=d[y].fa;
 29     int px=idf(x);int py=idf(y);
 30     con(d[x].ch[px^1],y,px);
 31     con(y,x,px^1);
 32     con(x,ff,py);
 33     pushup(y),pushup(x);
 34 }
 35 void splay(int x,int to)
 36 {
 37     to=d[to].fa;
 38     int y,px,py;
 39     while(d[x].fa!=to)
 40     {
 41         y=d[x].fa;
 42         px=idf(y),py=idf(x);
 43         if(d[y].fa==to) rot(x);
 44         else if(py==px){
 45             rot(y);
 46             rot(x);
 47         }else{
 48             rot(x);
 49             rot(x);
 50         }
 51     }
 52 }
 53 int Find(int w)
 54 {
 55     int x=root;
 56     while(x)
 57     {
 58         pushdown(x);
 59         if(d[d[x].ch[0]].sum>=w)
 60         {
 61             x=d[x].ch[0];
 62             continue;
 63         }
 64         w-=d[d[x].ch[0]].sum;
 65         if(w==1) return x;
 66         w--,x=d[x].ch[1];
 67     }
 68     return 0;
 69 }
 70 int build(int ff,int l,int r)
 71 {
 72     if(l>r) return 0;
 73     int x=++cnt;
 74     int mid=(l+r)>>1;
 75     d[x].id=mid-1,d[x].fa=ff,d[x].sum=1;
 76     d[x].ch[0]=build(x,l,mid-1);
 77     d[x].ch[1]=build(x,mid+1,r);
 78     pushup(x);
 79     return x;
 80 }
 81 void Print(int x)
 82 {
 83     pushdown(x);
 84     if(d[x].ch[0]) Print(d[x].ch[0]);
 85     if(d[x].id!=0&&d[x].id!=n+1) printf("%d ",d[x].id);
 86     if(d[x].ch[1]) Print(d[x].ch[1]);
 87 }
 88 int main()
 89 {
 90     //freopen("testdata.in","r",stdin);
 91     scanf("%d%d",&n,&m);
 92     int x,y;
 93     root=build(0,1,n+2);
 94     for(int i=1;i<=m;i++){
 95         scanf("%d%d",&x,&y);
 96         if(x==y) continue;
 97         int xx=Find(x);
 98         splay(xx,root);
 99         int yy=Find(y+2);
100         splay(yy,d[root].ch[1]);
101         d[d[d[root].ch[1]].ch[0]].mrk^=1;
102     }
103     Print(root);
104     return 0;
105 }

原文地址:https://www.cnblogs.com/guapisolo/p/9697023.html

时间: 2024-09-27 00:21:16

splay 文艺平衡树 (数据结构)的相关文章

[平衡树-Splay]文艺平衡树_区间翻转

题意 给你一个1-n的排列,1,2,...n 求翻转k次之后的序列 例如:1,2,3,5,4 翻转2-4 -> 1,5,3,2,4 题解 首先,splay操作之后的中序遍历是不会发生变化的.初始序列无论splay多少次中序遍历不变 中序遍历有一个显而易见的性质,就是左子树和右子树交换之后,中序遍历也就翻转了. 题目中的翻转操作也可以通过某个点的左右子树交换 问题1:这个点的子树要锁定题目要求的区间里,即这个点的的子树要覆盖这个区间,这样才能通过左右子树交换解决问题 我们可以通过splay操作让这

Tyvj P1729 文艺平衡树 Splay

题目: http://tyvj.cn/p/1729 P1729 文艺平衡树 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 此为平衡树系列第二道:文艺平衡树 描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入格式 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数

P3391 【模板】文艺平衡树(Splay)

题目背景 这是一道经典的Splay模板题--文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入输出格式 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,?n?1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r

BZOJ3223: Tyvj 1729 文艺平衡树 [splay]

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3595  Solved: 2029[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

洛谷P3391 【模板】文艺平衡树(Splay)

题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入输出格式 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,?n−1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r

P3391 【模板】文艺平衡树(Splay)新板子

P3391 [模板]文艺平衡树(Splay) 题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入输出格式 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,?n−1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,

洛谷P3391 【模板】文艺平衡树(Splay)(FHQ Treap)

题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入输出格式 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,?n−1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r

【模板】文艺平衡树(Splay)

题目背景 这是一道经典的Splay模板题--文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入输出格式 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,?n?1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r

洛谷 P3391 【模板】文艺平衡树(Splay)

题目背景 这是一道经典的Splay模板题--文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是 (1,2,?n?1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1≤l≤r≤n 输出格式: 输出一行n个数字,表示原始序列经过m次变换后的结果