半懂不懂地敲完了代码,和当初理解伸展树一样,完全不懂。
但是,完全不懂我也写得出来,毕竟,对于模板能力我还是无比强大的。
详细的解说可以参考杨哲的论文,这里贴出来一些我到处搜刮且觉得不错的模板
首先是Access,Splay,Rotate
void rotate(Node *p)
{
Node *x = p->f;
x->down();p->down();
int d = p->d();
if (!x->check()) p->f = x->f;
else x->f->setc(p,x->d());
x->setc(p->ch[d^1],d);
p->setc(x,d^1);
x->maintain();
}
void Splay(Node *p)
{
p->down();
while (p->check())
{
Node *x = p->f;
if (!x->check()) rotate(p);
else p->d() == x->d() ? (rotate(x),rotate(p)) : (rotate(p),rotate(p));
}
p->maintain();
}
int Access(Node *p)
{
int ans = 0;
for (Node *q = null; p != null; p = p->f)
{
Splay(p);
p->ch[1] = q;
q->f = p;
(q = p)->maintain();
}
return ans;
}
非常工整漂亮~
其合并的核心还是那个maintain
还有剩下的f(),check(),d()详见下面的struct
struct Node
{
int size;
Node *ch[2],*f;
void maintain(){size = 1+ch[0]->size+ch[1]->size;}
Node (){f = ch[0] = ch[1] = null,size = 1;}
Node (int x){f = ch[0] = ch[1] = NULL,size = 0;}
bool check(){return f != null && (f->ch[0] == this || f->ch[1] == this);}
int d(){return f->ch[1] == this ? 1 : 0;}
void setc(Node *c,int d){ch[d] = c;c->f = this;}
};
虽然缩了行,但丝毫不影响可读性
换根操作,这个很简单
p[x]->ch[0]->f = null, p[x]->ch[0] = null, p[x]->f = p[y];
p[x]->maintain();
路径操作,比如查询最大值什么的
int query(Node *u,Node *v)
{
Access(u);
int ans = 0;
for (Node *q = null; v != null; v = v->f)
{
Splay(v);
if (v->f == null)
{
ans = max(v->ch[1]->sub_max,q->sub_max);
ans = max(ans,v->ch[1]->pre_max+q->pre_max+v->v);
return ans;
}
v->setc(q,1);
(q = v)->maintain();
}
}
(这个是GSS7)
推荐几道题目:
bzoj 2002 弹飞绵羊
bzoj 道馆之战
spoj GSS7
spoj QTREE系列所有