莫队算法 ( MO's algorithm )
莫队算法是由清华大学神牛莫涛发明的一种处理区间问题的离线算法
算法核心是通过先将问询区间总长度平方分块、然后将所有的问询区间按照左端点所在的块编号排序、在同一块内的则按右端点升序
然后设置左右两个下标指针、每次都移动两个指针指向问询块的左右端点、在移动的过程中不断维护答案。
可以证明原本只通过两个下标指针移动来处理问询的方法最坏可达 O(N*Q) 经过莫队算法排序后可降为 O((N+Q)*sqrt(N))
所以莫队算法其实就是排个序
当然经过我粗略的概述肯定是无法讲清楚的,这里给出几个链接方便参考和学习此算法
一些题目
分析 :
对于每个区间、实际就是查询区间逆序对的个数。
看到数据范围和不强制在线考虑使用莫队算法解决、先确定分块长度然后对所有问询进行离线排序、关键在于怎么更新。
更新算法和指针左右移动密切相关,指针的移动可以看成从 左/右 添加或者删除一个数,那么这就很好做了
在左边添加一个数、比这个数小的都贡献了一个逆序对、加上
在右边添加一个数、比这个数大的都贡献了一个逆序对、加上
在左边删除一个数、原本比这个数小的都贡献了一个逆序对、减去
在右边删除一个数、原本比这个数大的都贡献了一个逆序对、减去
注意一下左右指针移动的时候是先指针移动再更新还是先更新再移动
#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 )的更多相关文章
- 【BZOJ】4129: Haruna’s Breakfast 树分块+带修改莫队算法
[题意]给定n个节点的树,每个节点有一个数字ai,m次操作:修改一个节点的数字,或询问一条树链的数字集合的mex值.n,m<=5*10^4,0<=ai<=10^9. [算法]树分块+ ...
- 【BZOJ】2120: 数颜色 带修改的莫队算法
[题意]给定n个数字,m次操作,每次询问区间不同数字的个数,或修改某个位置的数字.n,m<=10^4,ai<=10^6. [算法]带修改的莫队算法 [题解]对于询问(x,y,t),其中t是 ...
- 「日常训练&知识学习」莫队算法(二):树上莫队(Count on a tree II,SPOJ COT2)
题意与分析 题意是这样的,给定一颗节点有权值的树,然后给若干个询问,每次询问让你找出一条链上有多少个不同权值. 写这题之前要参看我的三个blog:Codeforces Round #326 Div. ...
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose) 【莫队算法模版】
任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=2038 题意概括: 有 N 只袜子(分别编号为1~N),有 M 次查询 (L, R)里面随机 ...
- NBUT 1457 莫队算法 离散化
Sona Time Limit:5000MS Memory Limit:65535KB 64bit IO Format: Submit Status Practice NBUT 145 ...
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 7687 Solved: 3516[Subm ...
- NPY and girls-HDU5145莫队算法
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description ...
- Codeforces617 E . XOR and Favorite Number(莫队算法)
XOR and Favorite Number time limit per test: 4 seconds memory limit per test: 256 megabytes input: s ...
- Bzoj 2038---[2009国家集训队]小Z的袜子(hose) 莫队算法
题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=2038 Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色 ...
随机推荐
- AndroidStudio ADB WIFI :adb wifi scan ip address
笔记本使用Android studio的adb wifi插件时,AS 最下方报 adb wifi scan ip address.一直无法使用. 解决办法: ----在Terminal窗口中输入: a ...
- Java实验报告四
一.实验目的 (1)掌握类的继承方法: (2)变量的继承和覆盖,方法的继承.重载和覆盖实现: 二.实验内容 1)实验代码 import java.util.Scanner; public class ...
- Rsync+sersync(inotify)实现数据实时双向同步
目录 Rsync+Sersync数据实时同步(双向) 服务介绍 节点声明 编译环境配置 安装Rsync 编辑Rsync配置文件 配置文件解析 配置密码文件 启动rsync验证 安装sersync服务 ...
- Java中的模板设计模式,太实用了!
顾名思义,模板设计模式就是将许多公用的常用的代码封装成一个模板,我们只需要实现不同的业务需求的代码,然后和模板组合在一起,那么就得到完整的逻辑. 在我们的日常开发中,常用的模板模式有两种实现方式:继承 ...
- python网络爬虫(2)回顾Python编程
文件写入 def storFile(data,fileName,method='a'): with open(fileName,method,newline ='') as f: f.write(da ...
- 曹工说Spring Boot源码(5)-- 怎么从properties文件读取bean
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- js 元素offset,client , scroll 三大系列总结
1,element.offsetWidth : 包括 padding 和 边框 2,element.clientWidth : 包括 padding ,不包含边框 , 内容超出会溢出盒子的时候,就用s ...
- kali下纯文本与窗口环境切换
切到纯文本环境,想返回 试了半天ctrl+alt+f7不行, 最后我想试试ctrl+alt+f8竟然成了: 而且那是之前以root账户登录图像界面时切换回去是f8,普通用户是f9 ,为何如此,我还不 ...
- Librepilot-Windows编译环境的搭建
1.安装Msys2 下载Msys2,下载地址 https://msys2.github.io,注意根据笔记本的型号选择32bit或64bit. 2.添加LibrePilot MinGW库 在 /e ...
- 【转】Linux添加虚拟网卡
转自:https://blog.csdn.net/hzhsan/article/details/44677867 有时候,一台服务器需要设置多个ip,但又不想添加多块网卡,那就需要设置虚拟网卡.这里介 ...