莫队算法

序列莫队:

有这样一类套路题:给出一个\([1,n]\)的区间,每次询问区间\([l,r]\)的某个值。

对于这类问题已有一个不错的“通解”:假设我们知道了区间\([l,r]\)的答案,那么如果区间\([l-1,r]\)\([l+1,r]\)\([l,r-1]\)\([l,r+1]\)的答案都能在\(O(p)\)的时间内计算出来,那么我们就可以通过莫队算法求解。

对于所有的\(m\)个询问,我们要确定一种最优的顺序,使得计算的代价尽可能小。

不难发现对于两个询问\([x_1,y_1]\)\([x_2,y_2]\),转移的代价为\(|x_1-x_2|+|y_1-y_2|\),即看成这两个点之间的曼哈顿距离,那么最优方案应该是所有点的曼哈顿距离最小生成树

但是求解最小生成树的代价太高,我们不如使用另一种方法:对整个区间分块\(sqrt(n)\)块,假设询问的两个端点所在的块的下标为\(a,b\),求出所有这样的下标,并对他们按\(a\)为第一关键字,\(b\)为第二关键字排序,则每次移动为\(O(n)\)的只有\(sqrt(n)\)次,其他每次移动均不超过\(\sqrt n\)次,所以总复杂度为\(O(np\sqrt n)\)


树上莫队:

这类问题往往是询问树上两点之间的什么东西之类,而对于子树的一般比较好做,这里不作讨论。

我们考虑使用DFS序来将树上的询问转化为区间的询问,这里我们使用括号序(即在进入结点和退出结点时各记录一次,用\(S_k,T_k\)分别表示进入和退出时刻),那么考虑两种情况:

  • \(u\)\(v\)是祖先与后代关系,那么询问区间为\([S_u,S_v]\)
  • \(u\)\(v\)是叔侄关系(●'◡'●),那么询问区间为\([T_u,S_v]+LCA_{u,v}\)

注意出现了两次的结点不能算到答案中。

posted @ 2017-01-28 15:43  Krew  阅读(124)  评论(0)    收藏  举报