[算法模版]莫队

[算法模版]莫队

莫队是一个极其有意思的玄学算法,常用于暴力骗分。

首先,莫队是通过暴力转移区间来求解答案的。那么显然,完成单组询问复杂度是\(O\left(x^{*}(|r 1-r 2|+|(l1-l2 |))\right.\)。其中\(x\)为每次的转移复杂度。

莫队算法的总复杂度是\(n \sqrt m\)。(虽然我也不知道怎么证的)

莫队的精髓在于将序列分块,块的大小也因题而异。对于不带修的普通莫队,最优分块方法是

而对于带修改的莫队,分块方法是:

带修莫队只要添加一个第三关键字——按照时间排序即可。

再介绍一种极其玄学的奇偶优化:

我们只需把

int cmp(query a, query b) {
    return belong[a.l] == belong[b.l] ? a.r < b.r : belong[a.l] < belong[b.l];
}

换成

int cmp(query a, query b) {
    return (belong[a.l] ^ belong[b.l]) ? belong[a.l] < belong[b.l] : ((belong[a.l] & 1) ? a.r < b.r : a.r > b.r);
}

即可。

具体原理见:莫队——奇偶优化详解



这里放一道莫队+玄学优化卡常能过的暴力题。

[SDOI2009]HH的项链

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 500500
using namespace std;
int block[maxn],val[maxn],n,m,cnt[1020000],tot,ans[maxn];
struct gg {
    int l,r,id;
}q[500500];
inline void add(int col) {
    if(!cnt[col])tot++;
    cnt[col]++;
}
inline void del(int col) {
    if(cnt[col]==1)tot--;
    cnt[col]--;
}
inline bool cop(gg x,gg y){return (block[x.l]^block[y.l])?x.l<y.l:((block[x.l]&1)?(x.r<y.r):(x.r>y.r));}
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++){scanf("%d",&val[i]);}
    scanf("%d",&m);
    int bl=n/sqrt(m*2/3);
    for(int i=1;i<=n;i++){block[i]=(i-1)/bl+1;}
    for(int i=1;i<=m;i++){scanf("%d%d",&q[i].l,&q[i].r);q[i].id=i;}
    sort(q+1,q+1+m,cop);
    int l=1,r=1;cnt[val[1]]++;tot=1;
    for(int i=1;i<=m;i++) {
        int tl=q[i].l,tr=q[i].r;
        while(tl<l){l--;add(val[l]);}
        while(r<tr){r++;add(val[r]);}
        while(l<tl){del(val[l]);l++;}
        while(tr<r){del(val[r]);r--;}
        ans[q[i].id]=tot;
    }
    for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
}

原文地址:https://www.cnblogs.com/GavinZheng/p/11277204.html

时间: 2024-08-30 02:54:43

[算法模版]莫队的相关文章

【算法】莫队算法初探

[算法介绍] 莫队算法是用于离线处理处理区间问题的一类算法,非常易于理解和上手,应用面十分广泛,甚至还可以在树上进行操作. 当我们得到$[L,R]$的答案之后,如果能够以较低的复杂度扩展得到$[L-1,R],[L+1,R],[L,R-1],[L,R+1]$的答案,我们就可以使用莫队算法,通常这个扩展的复杂度是$O(1)$或$O(logn)$. 如果我们对于每个询问都暴力移动左右端点,那么复杂度肯定是$O(n^2)$的,而莫队算法的精髓就在于结合了分块的思想. 设扩展一次的复杂度为$O(f(n))

算法之 莫队 区间处理神器orz

例题:luogu P1972 [SDOI2009]HH的项链 题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了.于是,他只好求助睿智的你,来解决这个问题. 输入输出格式 输入格式: 第一行:一个整数N,表示项链的长度. 第二行

CSU 1515 Sequence (莫队算法)

题意:给n个数,m个询问.每个询问是一个区间,求区间内差的绝对值为1的数对数. 题解:先离散化,然后莫队算法.莫队是离线算法,先按按询问左端点排序,在按右端点排序. ps:第一次写莫队,表示挺简单的,不过这题之前乱搞一气一直TLE,莫队还是很强大的. 代码: #include <algorithm> #include <iostream> #include <cstdio> #include <cmath> #include <cstring>

D. Powerful array 莫队算法或者说块状数组 其实都是有点优化的暴力

莫队算法就是优化的暴力算法.莫队算法是要把询问先按左端点属于的块排序,再按右端点排序.只是预先知道了所有的询问.可以合理的组织计算每个询问的顺序以此来降低复杂度. D. Powerful array 典型的莫队算法题 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include

XOR and Favorite Number(莫队算法+分块)

E. XOR and Favorite Number time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standard output Bob has a favorite number k and ai of length n. Now he asks you to answer m queries. Each query is given by a pai

bzoj 4810 由乃的玉米田 - bitset - 莫队算法

由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐. 由乃认为玉米田不美,所以她决定出个数据结构题 这个题是这样的: 给你一个序列a,长度为n,有m次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是 否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1 ,2,3选出的这两个数可以是同一个位置的数 Input 第一行两个数n,m 后面一行n个数表示ai 后面m行每行四个数op

莫队算法详解和c实现

解析和实现 摘要:        莫队算法是一个对于区间.树或其他结构离线(在线)维护的算法,此算法基于一些基本算法,例如暴力维护,树状数组,分块,最小曼哈顿距离生成树,对其进行揉合从而产生的一个简单易懂且短小好写的算法.此算法在很多情况下可以很轻松的切掉一些复杂而且难写的数据结构问题. 关键词: 程序设计.算法.算法优化,暴力算法,分块算法,最小曼哈顿距离生成树. 背景: 众所周知,在OI竞赛.软件的设计中都会要求我们去处理各种各样的棘手的问题,而这些问题之中,有一大类就是维护问题:比如说对于

莫队算法心得

莫队算法:莫队算法使用范围: 1.支持离线操作. 2.在已有的序列左右加入或删除一个节点的复杂度很低. 3.外层复杂度为nsqrt(n). 我们将序列分为sqrt(n)块,每一块的大小也是sqrt(n),我们将询问按照左端点所在块为第一关键字,当左端点所在块一样是,如果编号是奇数块就按照右端点从升序排序,否则降序,可以想一想为什么,因为这样是一个Z字形.然后我们就可以按排完序后的顺序依次暴力转移了. 细节:转移时,初始l设为1,r设为0,这样方便.

信心题--FUOJ2226(莫队算法)

http://acm.fzu.edu.cn/problem.php?pid=2226 信心题,还说是信心题,题目给的真好.但是一点都不像信心题. 又是一个新的算法,莫队算法 莫队算法是一个用数组就可以轻易实现的神奇数据结构,可以处理一类无修改的离线区间查询问题(PS:暂时还没有遇到莫队解决更新区间查询的问题) 莫队算法可以在O(1),实现[l, r]到[l, r±1] / [l±1, r]的转移,然后我们就可以对所有查询分sqrt(n)块,把每个查询所在的块号当做第一关键字,右端点作为第二关键字