【splay】文艺平衡树 BZOJ 3223
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
思路
一看就知道是Splay。。。。如此经典。也是我写过的第二道splay。第一道是文本编辑器,但是本地测AC,提交的话就WA到死。。
只有区间翻转操作,如果我们要翻转[L,R]的话,就将L-1转到根,再将第R+1大的转到根的右子树。把根的右子树的左子树打上翻转标记就行了。
[1,L-1]和[R+1,n]都被转到别的地方去了,所以不会被旋转。
然后别的都是splay的基本操作啦~只要每次记得push_down就行啦~
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cmath> 7 #include <algorithm> 8 #include <queue> 9 #include <stack> 10 #include <map> 11 #include <set> 12 #include <list> 13 #include <vector> 14 #include <ctime> 15 #include <functional> 16 #define pritnf printf 17 #define scafn scanf 18 #define sacnf scanf 19 #define For(i,j,k) for(int i=(j);i<=(k);(i)++) 20 #define Clear(a) memset(a,0,sizeof(a)) 21 using namespace std; 22 typedef unsigned int Uint; 23 const int INF=0x3fffffff; 24 ///==============struct declaration============== 25 struct Node{ 26 int Val;bool Rev; 27 int siz; 28 Node *lc,*rc; 29 Node(){lc=rc=NULL;Rev=false;siz=1;} 30 }; 31 ///==============var declaration================= 32 const int MAXN=100050; 33 int n,q; 34 int num[MAXN]; 35 Node *root=NULL; 36 ///==============function declaration============ 37 void BuildTree(int l,int r,Node *&o); 38 int find_kth(int rank,Node *&o); 39 void Splay(int Rank,Node *&o); 40 void Rrotate(Node *&x);void Lrotate(Node *&x); 41 void push_down(Node *&x);void Output(Node *&x); 42 void update(Node *&x);void TestOutput(Node *&x); 43 ///==============main code======================= 44 int main() 45 { 46 #define FILE__ 47 #ifdef FILE__ 48 freopen("input","r",stdin); 49 freopen("output","w",stdout); 50 #endif 51 scanf("%d%d",&n,&q); 52 BuildTree(0,n+1,root);//TestOutput(root);printf("\n"); 53 while (q--){ 54 int L,R;scanf("%d%d",&L,&R); 55 if (L==R) continue; 56 Splay(L,root); 57 if (root->lc==NULL) 58 Splay(R+1,root->rc); 59 else 60 Splay(R+1-root->lc->siz,root->rc); 61 if (root->rc!=NULL&&root->rc->lc!=NULL) 62 root->rc->lc->Rev^=1; 63 //TestOutput(root);printf("\n"); 64 } 65 Output(root); 66 return 0; 67 } 68 ///================fuction code==================== 69 void BuildTree(int l,int r,Node *&o){ 70 int m=(l+r)>>1; 71 o=new(Node);o->Val=m; 72 if (l==r) return; 73 if (m>l) BuildTree(l,m-1,o->lc); 74 if (m<r) BuildTree(m+1,r,o->rc); 75 if (o->lc!=NULL) o->siz+=o->lc->siz; 76 if (o->rc!=NULL) o->siz+=o->rc->siz; 77 } 78 void Lrotate(Node *&x){ 79 push_down(x);push_down(x->lc); 80 Node *y=x->lc; 81 x->lc=y->rc; 82 y->rc=x;x=y; 83 update(x->rc);update(x); 84 } 85 void Rrotate(Node *&x){ 86 push_down(x);push_down(x->rc); 87 Node *y=x->rc; 88 x->rc=y->lc; 89 y->lc=x;x=y; 90 update(x->lc);update(x); 91 } 92 void push_down(Node *&x){ 93 if (x->Rev){ 94 swap(x->lc,x->rc); 95 x->Rev=false; 96 if (x->lc!=NULL) x->lc->Rev^=1; 97 if (x->rc!=NULL) x->rc->Rev^=1; 98 } 99 } 100 void update(Node *&x){ 101 x->siz=1; 102 if (x->lc!=NULL) x->siz+=x->lc->siz; 103 if (x->rc!=NULL) x->siz+=x->rc->siz; 104 } 105 void Splay(int Rank,Node *&o){ 106 int ls=0;push_down(o); 107 if (o->lc!=NULL) ls=o->lc->siz; 108 if (Rank==ls+1) return; 109 if (Rank>ls+1){ 110 Splay(Rank-ls-1,o->rc); 111 Rrotate(o); 112 } 113 else{ 114 Splay(Rank,o->lc); 115 Lrotate(o); 116 } 117 } 118 void Output(Node *&x){ 119 if (x==NULL) return; 120 push_down(x); 121 Output(x->lc); 122 if (x->Val!=0&&x->Val!=n+1) 123 printf("%d ",x->Val); 124 Output(x->rc); 125 } 126 void TestOutput(Node *&x){ 127 if (x==NULL) return; 128 if (!x->Rev){ 129 printf("%d(",x->Val); 130 TestOutput(x->lc); 131 printf(","); 132 TestOutput(x->rc); 133 printf(")"); 134 } 135 else{ 136 printf("%d(",x->Val); 137 TestOutput(x->rc); 138 printf(","); 139 TestOutput(x->lc); 140 printf(")"); 141 } 142 }
那个TestOutput是我用来在不改变标记的情况下看数的结构的。