感觉用指针写splay是不一样虽然说开始还有一点不习惯,但是还好吧,困难就是去战胜的啊,而且用指针写舒服多了,比起上次用了一天去 调一个splay确实进步了不少,加油吧。这里总结一下今天的经验
1.build函数虽然建树好像线段树(简直是神似),但是还是有很大区别,首先 线段树只用判断 r==l 就ok了,而splay还要判断 l==r-1 否则就会出现 r<l的情况,而且因为线段树中一个点表示一个区间,而splay中一个点代表的就是一个值,所以访问左儿子的时候是(l,mid-1)右儿子是(mid+1,r),剩下了一个mid作为它本身,其次,每次建完树以后需要有一个返回指针,今天就是被这里坑了,汗
2.在访问每一次的儿子节点的时候一定要注意先确定 儿子指针是否为空
3.注意在加懒惰标记的时候一定要先确保需要加的节点形成一颗子树,然后直接标记根(子树的)
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n;
struct Tree{
Tree* ch[3],*f;
int v,size,flag;
Tree(Tree* ls=NULL,Tree* rs=NULL,Tree* ff=NULL,int vv=0){
size=1;
ch[0]=ls;ch[1]=rs;f=ff;v=vv;
flag=0;
}
};
void push_up(Tree* u){
u->size =1;
if(u->ch[0]!=NULL)u->size+=u->ch [0]->size;
if(u->ch[1]!=NULL)u->size+=u->ch[1]->size;
}
void push_down(Tree* u){
if(!u->flag)return;
swap(u->ch[0],u->ch[1]);
if(u->ch[0]!=NULL)u->ch[0]->flag=!u->ch[0]->flag;
if(u->ch[1]!=NULL)u->ch[1]->flag=!u->ch[1]->flag;
u->flag=false;
}
Tree* root;
void Rotate(Tree* u){
if(u->f==NULL)return;
Tree* f=u->f;Tree* ff=f->f;
int d = u==(f->ch[1]);
push_down(f);
push_down(u);
Tree* o = u->ch[!d];
if(o!=NULL)o->f=f;
f->ch[d]=o;
u->f=ff;u->ch[!d]=f;f->f=u;
if(ff!=NULL)ff->ch[f==ff->ch[1]]=u;
push_up(f);
push_up(u);
}
void Splay(Tree* u){
while(u->f!=NULL){
Tree* f=u->f;Tree* ff=f->f;
if(ff==NULL){
Rotate(u);
root=u;
return ;
}
int d= u == f->ch[1];
int dd = f==ff->ch[1];
if(d==dd)Rotate(f);
else Rotate(u);
Rotate(u);
}
root=u;
}
Tree* build(int l,int r,Tree* f){
int x,y;
if(l==r){
scanf("%d",&x);
return new Tree(NULL,NULL,f,x);
}
if(l==r-1){
scanf("%d%d",&x,&y);
Tree* ll,*rr;
rr=new Tree(NULL,NULL,f,y);
ll=new Tree(NULL,NULL,rr,x);
rr->ch[0]=ll;
rr->size=2;
return rr;
}
int mid=(l+r)>>1;
Tree* rv=new Tree(NULL,NULL,f,0);
rv->ch[0]=build(l,mid-1,rv);
scanf("%d",&x);
rv->v=x;
rv->ch[1]=build(mid+1,r,rv);
push_up(rv);
return rv;
}
Tree* findk(Tree* u,int k){
push_down(u);
int ls=0;
if(u->ch[0]!=NULL)ls=u->ch[0]->size ;
if(k==ls+1)return u;
if(k<=ls)return findk(u->ch[0],k);
if(k>ls)return findk(u->ch[1],k-ls-1);
}
void Print(Tree* u){
push_down(u);
if(u->ch[0]!=NULL)Print(u->ch[0]);
printf("%d ",u->v);
if(u->ch[1]!=NULL)Print(u->ch[1]);
}
int main(){
scanf("%d",&n);
root=build(1,n,NULL);
/*Print(root);
printf("\n");*/
int cnt=0;
while(true){
if(cnt>100000){
puts("-1");
return 0;
}
int v;
Tree* fir=findk(root,1);
//printf("%d ",fir->v);
if(fir->v!=1) v=fir->v;
else break;
cnt++;
if(v+1<=n){
Splay(findk(root,v+1));
if(root->ch[0]!=NULL)root->ch[0]->flag=!root->ch[0]->flag;
}
else {
root->flag=!root->flag ;
}
}
printf("%d",cnt);
return 0;
}