莫队算法学习小记

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

一个优雅的暴力

对于一个询问区间[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视情况而定。

带修改?

那么把排序的关键字改成三维就好了。
具体请看a_crazy_czy的blog

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值