莫队算法学习小记

先前还以为莫队算法是一个高级的东西。
可是仔细学习了一下,才发现这东西应该叫做——

一个优雅的暴力

对于一个询问区间[l,r],如果我们可以O(1)的得到区间[l,r-1],[l,r+1],[l-1,r],[l+1,r]的答案,那么从这个询问转移到另一个询问的时间复杂度为O(|l-l’|+|r-r’|)。
那我们可以确定一个解决询问的顺序,从而使复杂度达到O(n^1.5)
我们把每个询问看做二位平面上的一个点,那么如果我们对这个东西做最小生成树,那么沿着树边做一定是最优解。
不管你会不会,反正我不会。
但是,如果莫队算法这么复杂的话,它也不会这么普及。
这个算法有一个优雅的替代品——分块(分块大法好)。
我们把所有的询问排序,第一关键字为左端点所在块的编号,第二关键字为右端点的编号。
为什么这样做也是O(n^1.5)的呢?
考虑i和i+1,若它们在同一块里,那么r最多增加n。单调递增,这样的东西最多有n^0.5个,所以复杂度为O(n^1.5)。
若它们在不同的块,那么r的变化也是n。这样的东西也有n^0.5个,所以也是O(n^1.5)
那么总的复杂度就是O(n^1.5)

Code

    pl=1;
    fo(i,1,m) {
        if (pr<ask[i].r) fo(j,pr+1,ask[i].r) updata(j,1);
        else fo(j,ask[i].r+1,pr) updata(j,-1);
        if (pl<ask[i].l) fo(j,pl,ask[i].l-1) updata(j,-1);
        else fo(j,ask[i].l,pl-1) updata(j,1);
        pr=ask[i].r;pl=ask[i].l;
    }

updata视情况而定。

你可能感兴趣的:(莫队算法,学习小记)