这么炫酷的数据结构简直飘逸到不行,竟然在这么狂躁的状态下过了一遍基础题型,略浪费。
强项:在一维的情况下可以完成区间查询,更新,翻转,子区间的增删,确定前驱后即,总是一句话线段树能做的它就能做,线段树不太好做的他也能很方便的实现。
弱项:没有办法向更高维度扩展(反正本渣没有想出来),这也是一个局限吧。代码太长. . . . . 太致命了。
伸展操作:核心操作,通过一系列的旋转将某个节点旋转到目标位置。
void Rotate(int root,int dir)
{
st[st[root].pre].son[dir] = st[root].son[1^dir];
st[root].son[1^dir] = st[root].pre;
if(st[st[st[root].pre].pre].son[0] == st[root].pre)
st[st[st[root].pre].pre].son[0] = root;
else
st[st[st[root].pre].pre].son[1] = root;
int temp = st[root].pre;
st[root].pre = st[st[root].pre].pre;
st[temp].pre = root;
if(st[temp].son[dir] != -1)
st[st[temp].son[dir]].pre = temp;
Updata(temp);
Updata(root);
}
int Splay(int root,int goal)
{
while(st[root].pre != goal)
{
Rotate(root,(st[st[root].pre].son[0] == root ? 0 : 1));
}
return root;
}
确定待伸展节点位置的函数模板
int Search_Site(int root,int site)
{
Push_Down(root);
int temp;
if(st[root].ls + 1 == site)
temp = root;
else if(st[root].ls + 1 < site)
temp = Search_Site(st[root].son[1],site-st[root].ls-1);
else
temp = Search_Site(st[root].son[0],site);
Updata(root);
return temp;
}
1.通过虚拟根结点以及虚拟的两个区间端点在减少代码长度的同时避免RE。
2.对于任何一棵子树,其根结点代表为该子树的信息。
3.当查询区间[L,R]上的信息时,需将R+1旋转至根结点,再将L-1旋转至根结点,则此时根结点的左孩子的右子树代表的即为[L,R]。
4.大多时候,在伸展之前需将待伸展节点与目标位置路径上的延迟标记擦出(Push_Down && Push_Up,这个很像线段树)。