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

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

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

可以证明原本只通过两个下标指针移动来处理问询的方法最坏可达 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. Python_Onlineh_Hmework(基础篇,持续更新中...)

    1 递归 1.1 定义一个函数,求一个数的阶乘 def func(x): if x == 2: return 2 else: return x*func(x-1) a = func(4) print( ...

  2. tableau日常管理

    各文件位置: https://help.tableau.com/current/server-linux/zh-cn/cli_default_filepaths_tsm.htm ldap配置: htt ...

  3. hdoj4507(数位dp)

    题目链接:https://vjudge.net/problem/HDU-4507 题意:定义如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关—— 1.整数中某一位是7: 2.整数的每一位 ...

  4. C - 卿学姐与诡异村庄(并查集+One face meng bi)

    卿学姐与诡异村庄 Time Limit: 4500/1500MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit  ...

  5. vue单页(spa)前端git工程拆分实践

    背景 随着项目的成长,单页spa逐渐包含了许多业务线 商城系统 售后系统 会员系统 ... 当项目页面超过一定数量(150+)之后,会产生一系列的问题 可扩展性 项目编译的时间(启动server,修改 ...

  6. qt tableview里面添加控件

    在QStyledItemDelegate的paint方法里面 void MyItemModelDeletage::paint(QPainter *painter, const QStyleOption ...

  7. jsp+servlet实现文件上传下载

    相关素材下载 01.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  8. 解析html,提取元素参数

    r = s.get(loginurl, verify=False) dom = etree.HTML(r.content.decode("utf-8")) try: result[ ...

  9. iconv_open - 分配一个字符集转换的描述符

    总览 (SYNOPSIS) #include <iconv.h> iconv_t iconv_open (const char* tocode, const char* fromcode) ...

  10. 【转】Android编译系统详解(一)——build/envsetup.sh

    出处 http://www.cloudchou.com/android/post-134.html 本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接 准备好编译环境后,编译Rom的 ...