| ||||||||||
| 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