您的位置:首页 > 理论基础 > 数据结构算法

【算法】数据结构

2017-03-25 17:10 169 查看

【平衡树】★平衡树 by onion_cyc

 

【莫队算法】

问题:给定长度为n的序列和m个区间询问,支持快速增减相邻元素维护区间信息。

将询问按左端点分块,块大小为$Q=\frac{n}{\sqrt m}$,块内按右端点排序。

然后依次回答询问,需要O(1)从(l,r)转移到(l,r+1),(l,r-1),(l-1,r),(l+1,r)。

复杂度分析:

左端点的移动,每个询问至多移动Q次,复杂度O(mQ)。

右端点的移动,每个块内至多移动n次,复杂度O(n*n/Q)。

平衡之后可以得到最佳块大小,复杂度$O(n\sqrt m)$。

 

【堆】

二叉堆

void access(int x)
{
int y=0;
while(x)
{
splay(x);
t[x][1]=y;
y=x;x=f[x];
}
}
access(x)

 

<reserve>access(x);splay(x);g[x]^=1;

将x变成主链splay的根,翻转后x就是主链的根,即所在树lct的根。

<link>reserve(x);fa[x]=y;

将x变成所在lct的根,然后作为y的轻儿子连入。

<cut>reserve(x);access(y);splay(y);t[y][0]=f[x]=0;

reserve(x)使x成为该树根节点,access(y)使y接到主链上,splay(y)使y成为splay的根,此时x是y的左子节点(原树根),断连即可。

<findroot>将x变成主链splay的根之后,不断往左就能找到,一般用于判断两点是否连通(在同一棵树上)。

★例题:【BZOJ】2049: [Sdoi2008]Cave 洞穴勘测 LCT

 

一道神奇的题:[WerKeyTom_FTD的模拟赛]Sone0,下面几点比较有趣:

1.在原树形态的基础上,换根求新子树:分类讨论新根root和查询位置x的位置即可,不用真正换根。(重组病毒)

2.开方到区间全1即可返回。(花神游历各国)

3.动态树的链splay轮换:分别建形态splay和权值splay,改权只改权,改形一起改。

4.动态维护子树大小:sz记录每个节点的虚子树节点总数。

 

【点分治】

每次找到一个区域的重心,以重心为根划分成若干子区域。点分治中每个点都会作为重心一次,一条路径只会作为跨越重心的路径被访问一次,因此主要用于处理树上所有路径的询问问题。

这样至多log n层,所以总复杂度O(n log n)。需要特别注意点分治的常数很大。还需要注意点分治过程中的所有操作必须和点数相关(不能和权值相关),否则复杂度不对。

三种统计方法:

1.加所有子树信息,依次删除一棵子树进去统计后再加回。(4)

特点:最万能的方法,复杂度也最高,要求信息支持删除。

例题:【CodeForces】914 E. Palindromes in a Tree 点分治

2.加所有树的信息,然后进入每棵子树统计,然后再进入每棵子树删除来自同一棵子树的路径。(3)

特点:要求答案支持删除。

3.每棵子树 i 和前1~i-1棵子树的信息合并后加入。(2)

特点:路径只能单向统计。

例题:【BZOJ】2599: [IOI2011]Race 点分治

4.将所有子树的信息取出来单独处理。(1)

特点:适用于特殊的题目,例如排序双指针(n log2n),但是注意取出来后复杂度依然要保证O(点数)。

例题:【BZOJ】1468: Tree(POJ1741) 点分治

【dsu on tree】

例题:

 

 

未完待续——

 

【点分治】

其它:树的重心及动态维护

《分治算法在树的路径问题中的应用》

浅谈对点分治的一些理解

关于点分治的理解

例题一:树中点对

【树套树】

一个数据结构里附加了另一个数据结构的根节点,如树状数组套线段树、线段数套线段数,都是O(log2n)。

动态逆序对:一维序号一维大小,一行为一颗线段树,列为树状数组。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: