JZYZOJ1998 [bzoj3223] 文艺平衡树 splay 平衡树

http://172.20.6.3/Problem_Show.asp?id=1998

平衡树区间翻转的板子,重新写一遍,给自己码一个板子。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<cstdlib>
  7 using namespace std;
  8 const int maxn=100100;
  9 int c[maxn][2],fa[maxn],siz[maxn],rev[maxn];
 10 int n,m,rt;
 11 inline int read(){
 12     int x=0,f=1;char ch=getchar();
 13     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 14     while(ch>=‘0‘&&ch<=‘9‘){x*=10;x+=ch-‘0‘;ch=getchar();}
 15     return x*f;
 16 }
 17 inline void pushup(int x){//向上总结siz
 18     siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;
 19 }
 20 inline void pushdown(int x){//向下传递rev标记
 21     if(rev[x]){
 22         swap(c[x][0],c[x][1]);
 23         rev[c[x][0]]^=1;rev[c[x][1]]^=1;
 24         rev[x]=0;
 25     }
 26 }
 27 void build(int l,int r,int pa){//不完全二分建树。。
 28     if(l>r)return;
 29     if(l==r){
 30         fa[l]=pa;siz[l]=1;
 31         if(l<pa)c[pa][0]=l;
 32         else c[pa][1]=l;
 33         return;
 34     }
 35     int mid=(l+r)/2;
 36     build(l,mid-1,mid);build(mid+1,r,mid);
 37     if(mid<pa)c[pa][0]=mid;
 38     else c[pa][1]=mid;
 39     fa[mid]=pa;
 40     pushup(mid);
 41 }
 42 int find(int x,int rank){//二分查找排名为rank的数
 43     //因为建树的时候已经默认查找的数在数组中的序号就是它本身
 44     //操作不会改变一个节点的序号,只会改变点和点的联系,从而改变排列顺序
 45     pushdown(x);
 46     //find中的pushdown相当于为后面的splay“开路”
 47     int l=c[x][0],r=c[x][1];
 48     if(siz[l]+1==rank)return x;
 49     else if(siz[l]>=rank)return find(l,rank);
 50     else return find(r,rank-siz[l]-1);
 51 }
 52 void rotate(int x,int &k){//向上旋转
 53     int pa=fa[x];int gpa=fa[pa],l,r;
 54     if(c[pa][0]==x) l=0;
 55     else l=1; r=l^1;//上旋前x在pa的l方向
 56     if(pa==k) k=x;
 57     else{
 58         //如果x旋转不到k,需要关注上旋后和gpa的儿子关系
 59         //观察后面的调用,旋转到k时gpa的儿子关系相当于直接被继承,
 60         if(c[gpa][0]==pa)c[gpa][0]=x;
 61         else c[gpa][1]=x;
 62     }
 63     fa[x]=gpa;fa[pa]=x;fa[c[x][r]]=pa;
 64     c[pa][l]=c[x][r];c[x][r]=pa;
 65     pushup(x);pushup(pa);
 66
 67 }
 68 void splay(int x,int &k){
 69     while(x!=k){
 70         int pa=fa[x];int gpa=fa[pa];
 71         if(pa!=k){//这里的异或处理了顺位和逆位两种情况
 72             /*顺位先将pa上旋至k,逆位直接将x向上旋,
 73             避免树失衡。*/
 74             if((c[pa][0]==x)^(c[gpa][0]==pa))rotate(x,k);
 75             else rotate(pa,k);
 76         }rotate(x,k);
 77     }
 78 }
 79 void rever(int l,int r){
 80     int x=find(rt,l),y=find(rt,r+2);//找到两个数的位置
 81     splay(x,rt);splay(y,c[x][1]);//将两个数调为根和其rc
 82     //此时,两个数之间的数都在根的rc的lc上
 83     /*    我们开始开始的建树从1到n+2就是为了将1和n+2作为边界
 84     事实上进行操作的是2到n+1这n个数。我们最后取的时候要减1。
 85     所以,翻转l+1到r+1即可。
 86     */
 87     rev[c[y][0]]^=1;
 88 }
 89 int main(){
 90     n=read();m=read();
 91     int x,y;
 92     build(1,n+2,0);rt=(n+3)/2;
 93     for(int i=1;i<=m;i++){
 94         x=read();y=read();
 95         rever(x,y);
 96     }
 97     for(int i=2;i<=n+1;i++){
 98         printf("%d ",find(rt,i)-1);
 99     }
100     return 0;
101 }

原文地址:https://www.cnblogs.com/137shoebills/p/8349742.html

时间: 2024-10-14 10:36:16

JZYZOJ1998 [bzoj3223] 文艺平衡树 splay 平衡树的相关文章

洛谷 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次变换后的结果

【BZOJ3224】Tyvj 1728 普通平衡树 Splay

Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大于x,且最小的数) Input 第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6) Output 对于操作3,4,5,6每行输

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个数,这个序列依次

[BZOJ3223] [Tyvj1729] 文艺平衡树 (splay)

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

[Bzoj3223][Tyvj1729] 文艺平衡树(splay/无旋Treap)

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3223 平衡树处理区间问题的入门题目,普通平衡树那道题在维护平衡树上是以每个数的值作为维护的标准,而处理区间问题时,维护平衡树的应该是每个位置的下标,所以平衡树中序遍历时应该是当前区间的样子.例如: {1 2 3 4 5}翻转区间1 3,则中序遍历应该输出{3,2,1,4,5}. 提供splay和无旋Treap的做法. splay做法: 1 #include<bits/stdc++.h>

[bzoj3223]文艺平衡树[splay]

//BY HZWER 1 #include<iostream> 2 #include<cstdio> 3 4 using namespace std; 5 6 inline int read() 7 { 8 int x=0,f=1;char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9'){x=x*10

[bzoj3223]文艺平衡树(splay区间反转模板)

解题关键:splay模板题. #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> using namespace std; typedef long long ll; const int N = 100005; int ch[N][2],par[N],val[N],cnt[

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表示翻转操作次数

[BZOJ3223]文艺平衡树 无旋Treap

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB 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<