本文共 4672 字,大约阅读时间需要 15 分钟。
学习伸展树,个人觉得其实思想其实挺容易懂的:
一、(二八原则)20%的数据是经常操作的,而剩下80%的数据一般都不怎么会管!
二。旋转到根:每插入或者删除一个结点,都把插入的结点(删除结点的孩子)旋转到根。
最难理解的是代码:我自己在网上找了很久,找到我认为比较容易理解的代码,就拿来分析了:(POJ3580)http://www.cnblogs.com/Delostik/archive/2011/07/26/2116991.html
向这位大年致敬,我个人觉得代码写得相当有水平!
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <cmath>
- #define INF ~0u>>1
- #define NIL SPLAY
- #define MN 200005
- using namespace std;
- int n,m,l,r,x,pos;
- char s[10];
- struct SPLAYTREE{
- struct NODE{
- int key,minv,size,add;
- bool rev;
- NODE *left,*right,*father;
- NODE (){}
- NODE(int _key):key(_key){minv=_key,size=1,add=0,rev=false;}
- }SPLAY[MN],*SP,*root,*head,*tail;
-
- void init(){
- SP=NIL;
- NIL->key=NIL->minv=INF,NIL->size=0;NIL->rev=false;NIL->add=0;
- NIL->left=NIL->right=NIL->father=NIL;
- head=new(++SP)NODE(INF);
- head->left=head->right=head->father=NIL;
- tail=new(++SP)NODE(INF);
- tail->left=tail->right=tail->father=NIL;
- head->right=tail,tail->father=head,head->size++;
- root=head;
- }
-
- void pushdown(NODE *&t){
- if(t->rev){
- swap(t->left,t->right);
- t->left->rev=!t->left->rev;
- t->right->rev=!t->right->rev;
- t->rev=false;
- }
- if(t->add){
- if(t->left!=NIL){
- t->left->key+=t->add;
- t->left->minv+=t->add;
- t->left->add+=t->add;
- }
- if(t->right!=NIL){
- t->right->key+=t->add;
- t->right->minv+=t->add;
- t->right->add+=t->add;
- }
- t->add=0;
- }
- }
-
- void update(NODE *&t){
- t->size=t->left->size+t->right->size+1;
- t->minv=min(t->key,min(t->left->minv,t->right->minv));
- }
-
- void zig(NODE *&t){
- NODE *f=t->father,*r=t->right;
- pushdown(f->right);
- pushdown(t->left);
- pushdown(t->right);
- t->father=f->father;
- if(f==root) root=t;
- else{
- if(f->father->left==f) f->father->left=t;
- else f->father->right=t;
- }
- t->right=f,r->father=f,f->father=t,f->left=r;
- update(f);update(t);
- }
-
- void zag(NODE *&t){
- NODE *f=t->father,*l=t->left;
- pushdown(f->left);
- pushdown(t->left);
- pushdown(t->right);
- t->father=f->father;
- if(f==root) root=t;
- else{
- if(f->father->left==f) f->father->left=t;
- else f->father->right=t;
- }
- t->left=f,l->father=f,f->father=t,f->right=l;
- update(f);update(t);
- }
-
- void splay(NODE *&root,NODE *&t){
- pushdown(t);
- while(root!=t){
- if(t->father==root){
- if(t->father->left==t) zig(t);
- else zag(t);
- }
- else{
- if(t->father->father->left==t->father){
- if(t->father->left==t) zig(t->father),zig(t);
- else zag(t),zig(t);
- }else{
- if(t->father->left==t) zig(t),zag(t);
- else zag(t->father),zag(t);
- }
- }
- }
- }
-
-
-
- void insert(int key,int pos){
- NODE *t=new(++SP)NODE(key);
- t->left=t->right=t->father=NIL;
- NODE *r=root,*p;
- bool flag=false;
- while(pushdown(r),r!=NIL){
- p=r,r->size++;
- if(r->left->size+1>pos)r=r->left,flag=false;
- else pos-=r->left->size+1,r=r->right,flag=true;
- }
- if(flag) p->right=t;
- else p->left=t;
- t->father=p;
- splay(root,t);
- }
-
- void select(NODE *&root,int pos){
- NODE *r=root;
- while(pushdown(r),r->left->size+1!=pos){
- if(r->left->size+1>pos) r=r->left;
- else pos-=r->left->size+1,r=r->right;
- }
- splay(root,r);
- }
-
- void remove(int pos){
- select(root,pos);
- if(root->left==NIL) root=root->right;
- else if(root->right==NIL) root=root->left;
- else{
- select(root->left,root->left->size);
- root->left->right=root->right;
- root->right->father=root->left;
- root=root->left;
- }
- root->father=NIL;
- update(root);
- }
-
- void plus(int l,int r,int a){
- select(root,l);
- select(root->right,r-l);
- NODE *t=root->right->left;
- t->add+=a,t->key+=a,t->minv+=a;
- splay(root,t);
- }
-
- void reverse(int l,int r){
- select(root,l);
- select(root->right,r-l);
- NODE *t=root->right->left;
- t->rev=!t->rev;
- splay(root,t);
- }
-
- void revolve(int l,int r,int a){
- select(root,l);
- select(root->right,r-l);
- select(root->right->left,root->right->left->size-a);
- select(root->right->left->right,root->right->left->right->size);
- NODE *p=root->right->left,*t=root->right->left->right;
- p->right=NIL;
- p->father->left=t,t->father=p->father;
- t->right=p,p->father=t;
- update(t);update(p);
- splay(root,p);
- }
-
- int query(int l,int r){
- select(root,l);
- select(root->right,r-l);
- return root->right->left->minv;
- }
- }tree;
-
- int main(){
- tree.init();
- scanf("%d",&n);
- for(int i=1;i<=n;i++){
- scanf("%d",&x);
- tree.insert(x,i);
- }
-
- scanf("%d",&m);getchar();
- while(m--){
- scanf("%s",s);
- switch(s[0]){
- case 'A':
- scanf("%d%d%d",&l,&r,&x);
- tree.plus(l,r+2,x);
- break;
- case 'I':
- scanf("%d%d",&pos,&x);
- tree.insert(x,pos+1);
- break;
- case 'D':
- scanf("%d",&pos);
- tree.remove(pos+1);
- break;
- case 'M':
- scanf("%d%d",&l,&r);
- printf("%d\n",tree.query(l,r+2));
- break;
- case 'R':
- if(s[3]=='E'){
- scanf("%d%d",&l,&r);
- tree.reverse(l,r+2);
- }else{
- scanf("%d%d%d",&l,&r,&x);
- if(x%(r-l+1)) tree.revolve(l,r+2,x%(r-l+1));
- }
- break;
- }
- getchar();
- }
- return 0;
- }
先把代码贴在这里,分析的过程下一篇写!