【总结】 莫队算法
前言
机房中的各位神仙都会莫队就我不会,然后如果有些题实在想不出也可以用这个做一下。
思路
如果一些操作可以在知道\(Ans(l,r)\)的情况下,\(O(1)\)的时间内求出\(Ans(l-1,r),Ans(l+1,r),Ans(l,r+1),Ans(l,r-1)\),那么就可以用莫队求解。
- 将操作离线
- 按照分块的思路排序(这是保证复杂度合法的关键)
- 对于每一个询问不断更新
- 总结答案,重新按照编号排序输出
复杂度证明
在此之前,给出每一个区间询问的排序方法
int bl[maxn];//bl数组用来记录每一个点属于哪个块
struct node{
int l,r;
}ques[maxm];
bool cmp(node a,node b){
if(bl[a.l]==bl[b.l])return a.r<b.r;
return a.l<b.l;
}
因为每一组的询问左界都是在一个块里面的,所以左界的更新不会超过\(sqrt(n)\);
如果左界不在一个块里面的话,复杂度就是\(O(m-sqrt(n))\)的。
又因为块只有\(sqrt(n)\)个,所以一定是可以的(想一想,为什么)
例题
Problem1
考虑拆分式子,发现本质是维护一个区间的平方和,然后就可以用莫队计算。
Problem2
国家集训队-数颜色
考虑这是一个带修改的莫队,怎么办呢?
带修改操作的莫队
每一次询问我们都是排序后一个一个做的对吧,那么我们可以不断的按照修改操作的顺序来修改这些颜色,如果少了就接着改,多了就改回去。
思路和莫队差不多,只是多了两个循环,判断改多了还是改少了。
Problem2
让我们回到那个问题,接着思考怎么做。
有了上面的思路,直接就可以写了,记录一下每一个询问前最后一次修改的编号,然后不断修改就好了。
后话
有没有什么神仙可以告诉我HH的项链在洛谷怎么过(用莫队)啊。80分实在是没救了。
块的大小大家可以将\(sqrt(n)\)和\(n^{\frac{2}{3}}\)拍一下。