【BZOJ 3223】文艺平衡树 模板题
就是打个翻转标记,下推标记时记得交换左右孩子指针,查询kth和中序遍历输出时也记得要下推标记同时交换指针,二者不可缺!←这是易错点
仿陈竞潇学长模板的代码:
#include<cctype> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct node{ node(); node *ch[2],*fa; short reversal; short pl(){return this==fa->ch[1];} int d,sum; void push(); void count(); }*null; int N,M; node::node(){ch[0]=ch[1]=fa=null;reversal=sum=d=0;} void node::push(){ if (this==null) return; if (reversal==1){ reversal=0; ch[0]->reversal^=1; ch[1]->reversal^=1; node *k=ch[0]; ch[0]=ch[1]; ch[1]=k; } } void node::count(){ sum=ch[0]->sum+ch[1]->sum+1; } namespace Splay{ node *ROOT; node *build(int l=1,int r=N){ if (l>r) return null; int mid=(l+r)>>1; node *ro=new node; ro->d=mid; ro->ch[0]=build(l,mid-1); ro->ch[1]=build(mid+1,r); ro->ch[0]->fa=ro; ro->ch[1]->fa=ro; ro->count(); return ro; } void Build(){ null=new node; *null=node(); ROOT=build(); ROOT->count(); } void rotate(node *k){ node *r=k->fa; if (r==null||k==null) return; r->push(); k->push(); int x=k->pl()^1; r->ch[x^1]=k->ch[x]; r->ch[x^1]->fa=r; if (r->fa==null) ROOT=k; else r->fa->ch[r->pl()]=k; k->fa=r->fa; r->fa=k; k->ch[x]=r; r->count(); k->count(); } void splay(node *r,node *tar=null){ for (;r->fa!=tar;rotate(r)) if (r->fa->fa!=tar)rotate(r->pl()==r->fa->pl()?r->fa:r); r->push(); } node *kth(int x){ node *r=ROOT; while (r!=null){ r->push(); if (r->ch[0]->sum>=x) r=r->ch[0]; else if (r->ch[0]->sum+1>=x) return r; else x-=r->ch[0]->sum+1,r=r->ch[1]; }return null; } void rollingover(int ll,int rr){ node *ln=kth(ll-1),*rn=kth(rr+1),*r; if ((ln==null)&&(rn==null)) r=ROOT; else if (ln==null){ splay(rn); r=ROOT->ch[0]; }else if (rn==null){ splay(ln); r=ROOT->ch[1]; }else{ splay(ln); splay(rn,ROOT); r=ROOT->ch[1]->ch[0]; }r->reversal=r->reversal^1; } void AC(node *r=ROOT){ if (r==null) return; r->push(); AC(r->ch[0]); printf("%d ",r->d); AC(r->ch[1]); } } int getint() { char c; while (!isdigit(c=getchar())); int a=c-'0'; while (isdigit(c=getchar())) a=a*10+c-'0'; return a; } int main() { N=getint();M=getint(); Splay::Build(); while (M--){ int l=getint(),r=getint(); Splay::rollingover(l,r); } Splay::AC(); return 0; }
自己写的62行简洁代码:
#include<cstdio> #include<algorithm> #define read(x) x=getint() using namespace std; inline int getint(){char c;int ret=0;for(c=getchar();c<'0'||c>'9';c=getchar());for(;c>='0'&&c<='9';c=getchar())ret=ret*10+c-'0';return ret;} struct node{ node(); node *fa,*ch[2]; int d,sum; bool rev; bool pl() {return this->fa->ch[1]==this;} void setc(node *r,bool c) {r->fa=this; this->ch[c]=r;} void push() {if (rev){swap(ch[0],ch[1]);ch[0]->rev^=1;ch[1]->rev^=1;rev=0;}} void count() {sum=ch[0]->sum+ch[1]->sum+1;} }*ROOT,*null; node::node(){fa=ch[0]=ch[1]=null;d=sum=rev=0;} int n,m; inline node *build(int l,int r){ if (l>r) return null; int mid=(l+r)>>1; node *k=new node; k->ch[0]=build(l,mid-1); k->ch[1]=build(mid+1,r); if (k->ch[0]!=null) k->ch[0]->fa=k; if (k->ch[1]!=null) k->ch[1]->fa=k; k->d=mid; k->count(); return k; } inline void Build() {null=new node;*null=node();ROOT=build(1,n);} inline void rotate(node *r){ node *f=r->fa; bool c=r->pl(); if (f!=ROOT) f->fa->setc(r,f->pl()); else r->fa=null,ROOT=r; f->setc(r->ch[!c],c); r->setc(f,!c); f->count(); } inline void update(node *r) {if (r!=null) update(r->fa); r->push();} inline void splay(node *r,node *tar=null){ update(r); for(;r->fa!=tar;rotate(r)) if (r->fa->fa!=tar) rotate(r->fa->pl()==r->pl()?r->fa:r); r->count(); } inline node *kth(int x){ if ((x==0)||(x==n+1)) return null; node *r=ROOT; while (1){ r->push(); if (r->ch[0]->sum>=x) r=r->ch[0]; else if (r->ch[0]->sum+1>=x) return r; else {x-=r->ch[0]->sum+1; r=r->ch[1];} } } inline void reversal(int l,int r){ node *ll=kth(l-1),*rr=kth(r+1); if ((ll==null)&&(rr==null)) ROOT->rev^=1; else if (ll==null) splay(rr),ROOT->ch[0]->rev^=1; else if (rr==null) splay(ll),ROOT->ch[1]->rev^=1; else splay(ll),splay(rr,ROOT),rr->ch[0]->rev^=1; } inline void AC(node *r) {if (r==null) return; r->push(); AC(r->ch[0]); printf("%d ",r->d); AC(r->ch[1]);} int main(){ read(n); read(m); Build(); int l,r; while (m--) {read(l); read(r); reversal(l,r);} AC(ROOT); return 0; }
然后就可以了
NOI 2017 Bless All