队友最近可能在学Splay,然后让我敲下HDU1754的题,其实是很裸的一个线段树,不过用下Splay也无妨,他说他双旋超时,单旋过了,所以我就敲来看下。但是之前写的那个Splay越发的觉得不能看,所以直接学习了大神的Splay树的写法,下面的代码是CLJ上的Splay模板,有很多值得借鉴的地方,代码量比自己写短好多,下面记录下心得。
1.结点标记的add,set直接写在结点里面,更容易理解也更容易明白。
2.pushDown,pushUp也写在Node里,感觉也是漂亮许多。
3.第一次看到的 Node mem[maxn],*C=mem; 写法,这样就不用每次都 &mem[top++],直接就用C++就好,挺好的。
4.写一个作为sentinel的null,这个应该也是一个很重要的认识了吧。
5.旋转和splay两个函数都写的好妙。
6.用get传出【l,r)的区间的结点,之前没有当成一个函数写不太漂亮。
附上大神的模板权当学习。
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #define INF 0x3fffffff #define maxn 200100 using namespace std; struct Node { Node *ch[2],*p; int size,val,mx; int set; bool rev; Node(){ size=0; val=mx=-INF; set=-1; } bool d(){ return this==p->ch[1]; } void setc(Node *c,int d){ ch[d]=c; c->p=this; } void setIt(int se){ set=mx=val=se; } void revIt(){ rev^=1; } void pushDown(); // pushDown(); void pushUp(){ size=ch[0]->size+ch[1]->size+1; mx=max(val,max(ch[0]->mx,ch[1]->mx)); } }Tnull,*null=&Tnull; Node mem[maxn+50],*C=mem; int a[maxn+50]; void Node::pushDown(){ if(set!=-1){ for(int i=0;i<2;++i){ if(ch[i]!=null) ch[i]->setIt(set); } set=-1; } if(rev){ swap(ch[0],ch[1]); for(int i=0;i<2;++i){ if(ch[i]!=null) ch[i]->revIt(); } rev=0; } } Node *make(int v){ C->ch[0]=C->ch[1]=null; C->size=1; C->val=C->mx=v; C->set=-1;C->rev=0; return C++; } Node *build(int l,int r) { if(l>=r) return null; int m=(l+r)>>1; Node *t=make(a[m]); // 根据数组建值,建空值则t=make(0); t->setc(build(l,m),0); t->setc(build(m+1,r),1); t->pushUp(); return t; } Node *root; void rot(Node *t){ Node *p=t->p; p->pushDown(); t->pushDown(); int d=t->d(); p->p->setc(t,p->d()); p->setc(t->ch[!d],d); t->setc(p,!d); p->pushUp(); if(p==root) root=t; } void splay(Node *t,Node *f=null){ while(t->p!=f){ if(t->p->p==f){ rot(t); } else{ t->d()==t->p->d()? (rot(t->p),rot(t)):(rot(t),rot(t)); } } t->pushUp(); } Node *select(int k){ for(Node *t=root;;){ t->pushDown(); int c=t->ch[0]->size; if(k==c) { return t; } if(k>c) { k-=c+1,t=t->ch[1]; } else{ t=t->ch[0]; } } } Node*&get(int l,int r){ //[l,r) Node *L=select(l-1); Node *R=select(r); splay(L); splay(R,L); return R->ch[0]; } int n,m; int main() { while(cin>>n>>m) { C=mem; for(int i=1;i<=n;++i){ scanf("%d",&a[i]); } root=build(0,n+2); root->p=null; char str[3];int l,r; for(int i=0;i<m;++i){ scanf("%s%d%d",str,&l,&r); if(strcmp(str,"Q")==0){ Node*&t=get(l,r+1); printf("%d\n",t->mx); } else{ Node*&t=get(l,l+1); t->setIt(r); } } } return 0; }