莫队算法是由清华大学神牛莫涛发明的一种处理区间问题的离线算法

算法核心是通过先将问询区间总长度平方分块、然后将所有的问询区间按照左端点所在的块编号排序、在同一块内的则按右端点升序

然后设置左右两个下标指针、每次都移动两个指针指向问询块的左右端点、在移动的过程中不断维护答案。

可以证明原本只通过两个下标指针移动来处理问询的方法最坏可达 O(N*Q) 经过莫队算法排序后可降为 O((N+Q)*sqrt(N))

所以莫队算法其实就是排个序

当然经过我粗略的概述肯定是无法讲清楚的,这里给出几个链接方便参考和学习此算法

莫队算法还是莫队算法当然还是莫队算法

一些题目

BZOJ Mato的文件管理

分析 :

对于每个区间、实际就是查询区间逆序对的个数。

看到数据范围和不强制在线考虑使用莫队算法解决、先确定分块长度然后对所有问询进行离线排序、关键在于怎么更新。

更新算法和指针左右移动密切相关,指针的移动可以看成从 左/右 添加或者删除一个数,那么这就很好做了

在左边添加一个数、比这个数小的都贡献了一个逆序对、加上

在右边添加一个数、比这个数大的都贡献了一个逆序对、加上

在左边删除一个数、原本比这个数小的都贡献了一个逆序对、减去

在右边删除一个数、原本比这个数大的都贡献了一个逆序对、减去

注意一下左右指针移动的时候是先指针移动再更新还是先更新再移动

#include<bits/stdc++.h>
#define lowbit(i) (i & (-i))
using namespace std;
;
struct QUERY{
    int L, R, Len, id;
    bool operator < (const QUERY &rhs) const{
        if((L/Len) == (rhs.L/rhs.Len)) return R < rhs.R;
        else return (L/Len) < (rhs.L/rhs.Len);
    };
}Q[maxn]; int ans[maxn];

int arr[maxn], N;
int uni[maxn], uniLen;

int Bit[maxn];

inline void BitAdd(int i, int val)
{
    while(i <= N){
        Bit[i] += val;
        i += lowbit(i);
    }
}

int BitSum(int i)
{
    ) ;
    ;
    ){
        ret += Bit[i];
        i -= lowbit(i);
    }return ret;
}

int GetVal(int i)
{
    int ret = lower_bound(uni, uni+uniLen, arr[i]) - uni;
    return ++ret;
}

int main(void)
{
    scanf("%d", &N);
    ; i<N; i++) scanf("%d", &arr[i]), uni[i] = arr[i];

    sort(uni, uni+N);
    ///题目貌似没说每个元素的大小,干脆离散化好了
    uniLen = unique(uni, uni+N) - uni;

    int qNum, sqrt_N = (int)sqrt(N);
    scanf("%d", &qNum);
    ; i<qNum; i++){
        scanf("%d %d", &Q[i].L, &Q[i].R);
        Q[i].Len = sqrt_N;
        Q[i].id = i;
    }

    sort(Q, Q+qNum);

    ;
    curL = , curR = ;
    ; i<qNum; i++){
        ///在左边添加一个数、比这个数小的都贡献了一个逆序对、加上
        while(curL > Q[i].L){
            curL--;
            val = GetVal(curL-);
            BitAdd(val, );
            CurAns += BitSum(val-);
        }

        ///在右边添加一个数、比这个数大的都贡献了一个逆序对、加上
        while(curR < Q[i].R){
            curR++;
            val = GetVal(curR-);
            BitAdd(val, );
            CurAns += curR - curL - BitSum(val-);
        }

        ///在左边删除一个数、原本比这个数小的都贡献了一个逆序对、减去
        while(curL < Q[i].L){
            val = GetVal(curL-);
            BitAdd(val, -);
            CurAns -= BitSum(val-);
            curL++;
        }

        ///在右边删除一个数、原本比这个数大的都贡献了一个逆序对、减去
        while(curR > Q[i].R){
            val = GetVal(curR-);
            BitAdd(val, -);
            CurAns -= curR - curL - BitSum(val-);
            curR--;
        }

        ans[Q[i].id] = CurAns;
    }

    ; i<qNum; i++) printf("%d\n", ans[i]);
    ;
}

莫队算法 ( MO's algorithm )的更多相关文章

  1. 【BZOJ】4129: Haruna’s Breakfast 树分块+带修改莫队算法

    [题意]给定n个节点的树,每个节点有一个数字ai,m次操作:修改一个节点的数字,或询问一条树链的数字集合的mex值.n,m<=5*10^4,0<=ai<=10^9. [算法]树分块+ ...

  2. 【BZOJ】2120: 数颜色 带修改的莫队算法

    [题意]给定n个数字,m次操作,每次询问区间不同数字的个数,或修改某个位置的数字.n,m<=10^4,ai<=10^6. [算法]带修改的莫队算法 [题解]对于询问(x,y,t),其中t是 ...

  3. 「日常训练&知识学习」莫队算法(二):树上莫队(Count on a tree II,SPOJ COT2)

    题意与分析 题意是这样的,给定一颗节点有权值的树,然后给若干个询问,每次询问让你找出一条链上有多少个不同权值. 写这题之前要参看我的三个blog:Codeforces Round #326 Div. ...

  4. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) 【莫队算法模版】

    任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=2038 题意概括: 有 N 只袜子(分别编号为1~N),有 M 次查询 (L, R)里面随机 ...

  5. NBUT 1457 莫队算法 离散化

    Sona Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format: Submit Status Practice NBUT 145 ...

  6. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7687  Solved: 3516[Subm ...

  7. NPY and girls-HDU5145莫队算法

    Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description ...

  8. Codeforces617 E . XOR and Favorite Number(莫队算法)

    XOR and Favorite Number time limit per test: 4 seconds memory limit per test: 256 megabytes input: s ...

  9. Bzoj 2038---[2009国家集训队]小Z的袜子(hose) 莫队算法

    题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=2038 Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色 ...

随机推荐

  1. vue父子组件相互传值的实例

    当子组件需要向父组件传递数据时,就要用到自定义事件 子组件用 $emit()来触发事件,父组件用$on()来监昕子组件的事件 父组件也可以直接在子组件的自定义标签上使用 v-on 来监昕子组件触发的自 ...

  2. session 的理解

  3. Linux普通用户无法使用sudo

    问题描述: jenkins执行发布脚本,因为使用的是jenkins用户,所以有些shell命令需要 sudo 来执行,导致报错. + sudo rm -rf /usr/share/nginx/html ...

  4. Python进阶编程 类的成员

    类的成员 class A: company_name='老男孩' #静态变量 __iphone='1515151' #私有静态变量 def __init__(self,name,age): #特殊方法 ...

  5. Jquery复习(四)之text()、html()、val()

    三个简单实用的用于 DOM 操作的 jQuery 方法: text() - 设置或返回所选元素的文本内容 html() - 设置或返回所选元素的内容(包括 HTML 标记) val() - 设置或返回 ...

  6. node.js 设置静态文件托管

    1.在app.js文件中设置静态文件托管 /*应用程序入口文件*/ /*加载express模块*/ var express = require('express'); /*加载模板处理模块*/ var ...

  7. linux下mysql的常用命令

    更改mysql数据库root的密码 首次进入数据库是不用密码的: [root@localhost ~]# /usr/local/mysql/bin/mysql -uroot Welcome to th ...

  8. KVM虚拟化简介及安装

    kvm是基于图形化的linux操作的 安装图形化界面的知识点: 磁盘空间有两个词: 精简置备:我先在我系统里面去声明我要一个50G的空间,但是呢,我不会把50G都分给你,你用多少,我分给你多少,但是做 ...

  9. Linux中配置jdk环境变量出错:bad ELF interpreter: No such file or directory解决方法

    yum install glibc.i686 重新安装,javac成功 如果还有如下类系错误 再继续安装包 error while loading shared libraries: libstdc+ ...

  10. Atcoder grand 025 组合数学塔涂色 贪心走路博弈

    A 略 B 题意:给你N个数(3e5) 每个数可以是0,a,b,a+b(3e5) 但是总数加起来要是定值K(18e10) 问总方法数mod 998244353 解: 把a+b的看成是一个a加上一个b的 ...