莫队算法
jiazhaopeng · · 个人记录
普通莫队
莫队算法是一种离线算法,通常有多次询问,每次询问一区间。通过对询问进行排序,区间的伸长缩短来实现。
Code
注:初始化有一种更简单的方法:l = 1, r = 0;
可以证明块大小为
设
例题
小B的询问
Tree and Queries (简单的拓展,搞一下dfs序,转化成序列问题即可)
小Z的袜子
带修莫队
支持修改的莫队。
加上一维时间轴。按照左端点所在块,右端点所在块,时间进行三关键字排序。
可以证明,块大小设为
具体来说,块大小为
Code
树上莫队
参考资料:oi-wiki
仅学了括号序树上莫队。可以解决链上问题。
当DFS进入一个点时将其加入序列(左括号);退出时再次加入序列(右括号)。得到的序列成为括号序。
对于一个直上直下的链
对于一个拐弯的链
Code
题目
糖果公园:带修树上莫队
回滚莫队
有些时候扩展的复杂度是
仍然类似普通莫队那样排序(
如果发现
可能需要用到可撤销数据结构。注意撤销时要撤销完所有需要撤销的东西。
详见oi-wiki
代码:
int nwl = 0, nwr = 0, lst = 0;
for (int i = 1; i <= m; ++i) {
int l = qy[i].l, r = qy[i].r, id = qy[i].id;
if (blong[l] != lst) {
...
res = stop = 0;
nwl = ed[blong[l]] + 1; nwr = ed[blong[l]];
lst = blong[l];//bug
}
if (blong[r] == blong[l]) ans[id] = jzpforce::sol(l, r);
else {
while (nwr < r) ++nwr, ins(a[nwr], nwr);
int memor = res, memop = stop;
while (nwl > l) --nwl, ins(a[nwl], nwl);
ans[id] = res;
res = memor;
nwl = ed[blong[l]] + 1;
while (stop > memop) cancl(stk[stop--]);
}
}