【概念】
蒟蒻的理解:对于 m m 个询问区间,对询问排序,每次统计答案时由另一个询问推导而出
具体比如说,对于区间询问 [li,ri] [ l i , r i ] 可以由询问 [li±1,ri±1] [ l i ± 1 , r i ± 1 ] 在 O(1) O ( 1 ) 的时间内转移而得
那么这个算法的
空间复杂度:视题目而变化,一般
O(n+m)
O
(
n
+
m
)
时间复杂度:
O(排序+∑转移)
O
(
排
序
+
∑
转
移
)
,一般
O(nm‾‾√)
O
(
n
m
)
比一般的暴力更优 剪枝dalao不要说话
【实现】
对于询问的转移大家都懂
对于
m
m
个区间询问的排序有几种做法:
①直接按以 li l i 为第一关键字,以 ri r i 为第二关键字进行排序
②按 li l i 进行分块,在每个块内按 ri r i 进行排序
③将询问映射到二维平面上,求MST
三种做法的编码复杂度和时间稳定程度都是递增的,可以根据题目的时限和出题人的变态程度自主选择
【Necklace】
【Profile】
给定序列{ ai a i },有 m m 个询问,每次询问区间中所有不同权值的和
【Solution】
一般来说会选分块加上拆分颜色二分查找,暴力骗分
但莫队可以较为高效地解决这类问题
因为跟着询问一遍扫过去可以不用开那么大的数组(蒟蒻同时也觉得这代码更好打)
看代码可能更好理解:
转移:
for(int i = 1; i <= m; i++){
while(r < g[i].r) add(a[++r]);
while(r > g[i].r) del(a[r--]);
while(l < g[i].l) del(a[l++]);
while(l > g[i].l) add(a[--l]);
res[g[i].id] = tmp;
}
排序:
sort(g+1, g+1+m, [](node a, node b){return a.l/unit != b.l/unit ? a.l/unit < b.l/unit : a.r < b.r;});
树上莫队
其实就是将线性的莫队转移到树上,有一个证明很严谨但很显然的博客vfleaking