莫队算法 ( 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每天早上都要耗费很久从一堆五颜六色 ...
随机推荐
- Mac022-brew安装tool
1.Mac上查看目录的树结构 Step1:安装tree命令 brew install tree Step2:某一目录下执行tree,会将该目录下的所有目录以树形结构显示 $ tree $ tree - ...
- 小记-----一些linux操作小操作
lrzsz工具 window系统与linux系统 文件互传 1.在linux系统命令行:sudo yum install lrzsz 或者 yum install lrzsz (输入一个 ...
- POJ - 1287 Networking (最小生成树&并查集
You are assigned to design network connections between certain points in a wide area. You are given ...
- LOJ167 康托展开 题解
题面 康托展开: 康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩. 康托展开的实质是计算当前排列在所有由小到大全排列中的名次,因此是可逆的. X = A[0] * (n-1)! ...
- C++中的数据类模板
1,预备知识: 1,模板参数可以是数值型参数(非类型参数): 1,代码示例: template <typename T, int N> void func() { T a[N]; // 使 ...
- CGAL 属性配置
libgmp-10.lib libmpfr-4.lib boost_system-vc120-mt-gd-1_63.lib D:\dev\CGAL-4.9\include D:\dev\CGAL-4. ...
- python pycharm 注册码
D87IQPUU3Q-eyJsaWNlbnNlSWQiOiJEODdJUVBVVTNRIiwibGljZW5zZWVOYW1lIjoiTnNzIEltIiwiYXNzaWduZWVOYW1lIjoiI ...
- 剑指offer-字符串的排列-数组-递归-动态规划-python
题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 输入描述: 输 ...
- echats 油表盘 鼠标拖动指针改变数值
近期需要做一个鼠标拖动完成油表盘数值改变的功能,使用canvas感觉太麻烦,而且指针不太好监听和拖动,只能另谋出路,在网上参考了某位大神的操作,最终选择了echats来解决这个问题.废话不多说,直接上 ...
- redis删除主从节点
1.删除一个Slave节点 ./redis-cli --cluster del-node 127.0.0.1:7001 74957282ffa94c828925c4f7026baac04a67e291 ...