Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
雁过留声——伸展树的应用首先感谢IceKingdom! 只有像他这样的好心人多一些, 我们这个社会才会更加和谐! 题目的叙述是相当“裸”的,明明白白地告诉, 要实现一个datastructure,支持几种操作。 一般来说,用于“折腾”序列的数据结构主要有以下几个: 链表 块状链表 伸展树 很明显,这题伸展树是一个绝佳的选择。 伸展树的一个重要的“基本”操作是“砍树”,即 把一个区间[x,y]的所有节点组织成一个子树。 这个实现是: 查找y+1 查找x-1 y+1的作子树即为所求! 当然,这个在实现的时候是需要特判三种情况的... 如果re了,不妨想想自己是否偷懒了。 对于区间Add,照搬线段树的思想,对每一个节点打一个delta标记。 我的习惯是: delta表示他的子孙中需要再增加的值,与自身无关。 这样,对于每一个add,把区间对应的子树“砍”出来, 根节点的delta key min三个值统统增加。 对于区间Reverse,继续打标记,记录rev表示他的子树是否需要翻转 注意:rev标记也与自身无关 Ins就用最朴素的写法好了,完成后不要忘记splay Delete的实现比较简单: 把它“砍”成一个子树,断开与父亲的链接,最后splay上去。 注意:要特判! Revolve比较“复杂” 首先,我们把它转换为交换区间[a,b] [b+1,c] 先把[a,c]砍出来,然后在子树内部(就是把这个子树假想成原树) 查找c-a 查找b+1-a 之后把b+1-a的左子接到c-a的右子上,更新c-a b+1-a 这里还是有特判!!! 由于要不停的处理标记,所以一个好的标记系统是必须的。 我的策略:对每一个节点,定义updata()与down(),分别来更新于下传标记 struct node{ int sz,mn,delta,key; char rev; node *lc,*rc,*fa; node(){ sz=1;delta=0;rev=0; lc=rc=fa=NULL; } void updata(){ sz=1; if (lc)sz+=lc->sz; if (rc)sz+=rc->sz; mn=key; if (lc)if (mn>lc->mn+delta)mn=lc->mn+delta; if (rc)if (mn>rc->mn+delta)mn=rc->mn+delta; } void down(){ node *p; if (rev){ if (lc){ lc->rev^=1; p=lc->lc;lc->lc=lc->rc;lc->rc=p; } if (rc){ rc->rev^=1; p=rc->lc;rc->lc=rc->rc;rc->rc=p; } rev=0; } if (delta){ if (lc){ lc->key+=delta; lc->delta+=delta; lc->mn+=delta; } if (rc){ rc->key+=delta; rc->delta+=delta; rc->mn+=delta; } delta=0; } } }epool[NMax]; 沿着路径向下走的时候,沿路down, splay向上调整的时候,沿路updata struct Splay{ node *root,*etop; void zig(node *p){ node *q=p->fa; if (q==root)root=p; q->lc=p->rc; if (p->rc)p->rc->fa=q; p->rc=q;p->fa=q->fa;q->fa=p; if (p->fa){ if (p->fa->lc==q)p->fa->lc=p; else p->fa->rc=p; } q->updata();p->updata(); } void zag(node *p){ node *q=p->fa; if (q==root)root=p; q->rc=p->lc; if (p->lc)p->lc->fa=q; p->lc=q;p->fa=q->fa;q->fa=p; if (p->fa){ if (p->fa->lc==q)p->fa->lc=p; else p->fa->rc=p; } q->updata();p->updata(); } Splay(){ root=NULL; etop=epool; } void splay(node *p){ p->down(); while (p!=root){ p->updata(); if (p->fa==root){ if (p->type()==0)zig(p); else zag(p); break; }else if (p->fa->fa==root){ if (p->type()==0)zig(p); else zag(p); p->updata(); if (p->type()==0)zig(p); else zag(p); break; }{ if (p->type()==0){ if (p->fa->type()==0){ zig(p->fa); zig(p); }else{ zig(p); zag(p); } }else{ if (p->fa->type()==0){ zag(p); zig(p); }else{ zag(p->fa); zag(p); } } } } root->updata(); root->fa=NULL; } node *find(int x){ node *p; p=root; p->down(); while (!(p->lc && p->lc->sz==x) && !(!p->lc && x==0)){ if (p->lc && p->lc->sz>x){ p=p->lc; } else{ if (p->lc)x-=p->lc->sz; x--; p=p->rc; } p->down(); } splay(p); return p; } void Ins(int x,int a){ node *p; if (!root){ root=etop; etop->key=a; etop->updata(); etop++; }else{ p=root; while (1){ p->down(); if (p->lc && p->lc->sz>=x)p=p->lc; else if (!x){ p->lc=etop;etop->fa=p; etop->key=a;etop->updata(); splay(etop); etop++; break; }else if (p->rc){ if (p->lc)x-=p->lc->sz; x--; p=p->rc; }else{ p->rc=etop;etop->fa=p; etop->key=a;etop->updata(); splay(etop); etop++; break; } } } } WA的同志可以参考一下我的代码 最后在操作中,要绞尽脑汁特判,否则re得让人哭 void Reverse(int a,int b){ if (a>=b)return; node *p,*t; p=cuttree(a,b); t=p->lc;p->lc=p->rc;p->rc=t; p->rev^=1; } void Del(int a){ node *p,*q; if (!a){ p=find(a); root=p->rc; if (root)root->fa=NULL; }else if (a==root->sz-1){ p=find(a); root=p->lc; if (root)root->fa=NULL; }else{ p=find(a-1); q=find(a+1); p->rc=NULL; p->updata();q->updata(); } } void Revolve(int a,int b,int c){//exchange [a,b] [b+1,c] if (a>=c || a>b || b>=c)return; node *p,*bf,*br,*q,*t,*r; p=cuttree(a,c); bf=p->fa;br=root; root=p;p->fa=NULL; if (b+1==c){ q=find(c-a); t=q->lc;q->lc=q->rc;q->rc=t; }else{ q=find(c-a); r=find(b+1-a); q->rc=r->lc; r->lc=NULL; q->rc->fa=q; q->updata(); p->updata(); } root->fa=bf; if (bf){ if (bf->lc==p)bf->lc=root; else bf->rc=root; root=br; } } }; 最后,要记得REVOLVE的第三个参数可能很变态 以上的代码帮助我得到了7xxmsAC, 一看rank,发现自己写的常数其实不错...:) 再次感谢IceKingdom,他的5xxmsAC估计是加了无数针对性优化刷出来的吧 (*^__^*) Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator