• 莫队初探


    众所周知,分块是一种¥#@%¥#的暴力。

    而暴力+分块等于啥呢

    ¥#@%¥#的暴力  莫队!

    莫队是什么?克罗地亚男子足球队队长莫德里奇 国家队队长莫涛发表的算法 尊称为莫队

    具体的来说,只要一个答案区间 $[L,R]$的答案可以在 $O(1)$ 的时间复杂度下扩展到 $[L+1,R],[L-1,R],[L,R+1],[L,R-1]$并且出题人不强制在线 ,就可以愉快的使用莫队算法计算答案了!

    莫队算法的核心是通过上一次的询问 $[L_1,R_1]$ 来更新当前询问 $[L_2,R_2]$。时间复杂度是$ left | L_2-L_1 ight |+left |R_2-R_1 ight | $。

    但很显然,这样的算法是很naive的=_=。如果前一次的$L$与当前的$L$差距过大,你会愉快的TLE。我们需要对其进行优化。

    众所周知,分块是一种¥#@%¥#的暴力。

    而暴力+分块等于啥呢

    更¥#@%¥#的暴力  莫队!

    我们将所有的询问按照左端点$L$所在的块的序号$pos[L]$为第一关键字排序,以右端点$R$所在的块的序号$pos[R]$为第二关键字排序,这样便避免了上面提到的问题。这样做的理论复杂度是$O(n sqrt n)$的,但实际复杂度是$O(玄学???????能过就好)$。

    核心代码具体实现大概是下面这个样子↓↓↓

    int update(int...,int ...)
    {
        ....;
        return .....;
    }
    void solve()
    {
        int l=1,r=0;
        for(int i=1;i<=q;i++)
        {
            int size=(x[i].r-x[i].l+1);
            int fm=size*(size-1);
            for(;r<x[i].r;r++) 
                update(a[r+1],...);//注意扩展区间时要忽略开头(在L,R中计算过了)
            for(;r>x[i].r;r--) 
                update(a[r],...);//缩小区间时要忽略结尾(结尾并没有计算)
            for(;l<x[i].l;l++) 
                update(a[l]...);//同上 
            for(;l>x[i].l;l--) 
                update(a[l+1]...);
            ...//特判 
        }
    }

    莫队初步差不多就这样了。还有一种带修改莫队,具体的就是在操作后加一维x表示操作序号,在修改时可以向$[L,R,x pm 1]$扩展了。在扩展中若发现过程中操作序号发生改变,就把中间的操作干掉。

    口胡,不要介意。

    $Luogu P1903$是带修莫队裸题,$Luogu P 1972$是普通莫队裸题。

    0725 fix 带修莫队

    具体地说,第三维的移动可以理解为时光倒流(或加速),所以要将跳过的操作所做的贡献加回去;

    代码↓↓↓

    void work(int x,int y)
    {
        if(b[x].pos<=a[y].r&&b[x].pos>=a[y].l)
        {
            delet(c[b[x].pos]);
            add(b[x].num);
        }
        swap(b[x].num,c[b[x].pos]);//小优化 在更改完这次的颜色后 下次要撤回这次操作时不需要再写一个函数 比如这次将7修改成2 下次撤回操作的时候可以直接把2改回7 
    }
    for(;l<a[i].l;l++)
        delet(c[l]);
    for(;l>a[i].l;l--)
        add(c[l-1]);
    for(;r<a[i].r;r++)
        add(c[r+1]);
    for(;r>a[i].r;r--)
        delet(c[r]);
    for(;now<a[i].id;now++)
        work(now+1,i);
    for(;now>a[i].id;now--)
        work(now,i);

    $LHC$是我们的红太阳,没有他我们会死!!!!!

  • 相关阅读:
    WEBUS2.0 In Action
    WEBUS2.0 In Action
    WEBUS2.0 In Action
    WEBUS2.0 In Action
    在Linux查看版本命令
    Increasing heap size while building the android source code on Ubuntu 15.10
    在Linux中增加swap空间
    Patch
    使用Vim比较两个文件的内容
    @override 重写 与重载
  • 原文地址:https://www.cnblogs.com/handsome-wjc/p/11240368.html
Copyright © 2020-2023  润新知