莫队详解(先别看,有坑)

原创 2018年04月15日 21:36:04

引子:

终于,今天学习了莫队。

这可是一种高级的暴力,区间问题神器。



题目:

来看一道裸题。

有n个数,m个询问,每个询问有一对数x、y,求x~y中有多少个不同的数。



思路1:

自然而然想到暴力。

时间复杂度:O(nm),令人窒息。

代码就不贴了(人人都会)



思路2:

线段树或树状数组搞一搞。

然而这不是重点(代码复杂度相对而言较高)

代码稍后补上。



思路3:

重点来了!!!

我们可以优化一下思路1,就是暴力的升级版。

我们可以将这n个数分为块,每个块的长度为,这样就将一段数拆成了完整的块+不完整的块,那么我们只需要每次都对当前区间完整的块进行O(1)的询问就可以。

我们把每一个块按照右端点排序,不同的块按照左端点排序,就可以保证有序,然后直接操作即可。



代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
	int n,m,now;
	int p[500010],block[500010],hsh[500010],ans[500010];
	struct node{int x,y,id;} a[200010];
bool cmp(node x,node y)
{
	return block[x.x]==block[y.x]?x.y<y.y:x.x<y.x;
}
void init()
{
	int u=sqrt(n);
	for(int i=1;i<=n;i++)
		block[i]=(i-1)/u+1;
}
void move(int x,int d)
{
	if(d)
	{
		if(!hsh[p[x]]) now++;
		hsh[p[x]]++;
	}
	else
	{
		hsh[p[x]]--;
		if(!hsh[p[x]]) now--;
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&p[i]);
	scanf("%d",&m);
	init();
	for(int i=1;i<=m;i++)
	{
		scanf("%d %d",&a[i].x,&a[i].y);
		a[i].id=i;
	}
	sort(a+1,a+m+1,cmp);
	int l=0,r=0;
	for(int i=1;i<=m;i++)
	{
		while(l<a[i].x) move(l++,0);
		while(l>a[i].x) move(--l,1);
		while(r<a[i].y) move(++r,1);
		while(r>a[i].y) move(r--,0);
		ans[a[i].id]=now;
	}
	for(int i=1;i<=m;i++)
		printf("%d\n",ans[i]);
}

学习笔记——带修莫队

简介 普通的莫队算法相信大家都熟悉,那么如果有些问题加上修改操作是否可以用莫队维护呢?下面就介绍一种O(n53)O(n53)O(n^{\frac 5 3})的带修莫队算法。 算法详解 只需要...
  • Charlie_jilei
  • Charlie_jilei
  • 2018年02月25日 12:13
  • 70

codeforces86D 莫队算法

题目大意:给你n个数,m次询问,Ks为区间内s的数目,求区间[L,R]之间所有Ks*Ks*s的和。1 思路:直接用莫队算法,前面的博文讲过原理。这里再说一下增加和删除操作。因为要求Ks*Ks*s,所以...
  • qq_24477135
  • qq_24477135
  • 2016年05月18日 09:46
  • 406

莫队算法讲解 (详尽版)

莫队算法我早有耳闻。。可惜前不久才去学习。 但是自己看了看论文,也就1h左右,就能够全部理解了。 也就是说其实这个算法不难。。 好了,让我们进入正题。 我们首先来看一道例题: Des...
  • ThinFatty
  • ThinFatty
  • 2017年05月20日 16:25
  • 3188

带修改的莫队算法学习小记

简介莫涛大神创造出的离线询问算法的带修改版。 算法基础:需要掌握莫队算法,会打暴搜(暴力)。 一个叫莫的双端队列。 只支持单点修改操作方法普通的不带修改的莫队算法要把每个询问带上两个关键字排序,...
  • doyouseeman
  • doyouseeman
  • 2016年07月10日 09:15
  • 3750

分块与莫队

我们在做线段树等问题时,会通过将区间分成2部分,再将每一部分二分,成了一个较为严谨的树状结构。 而分块在复杂度或是结构上很不严谨,它的本质上只是将数据分成了一个个块状区域,每一个区域大小都由君定。 但...
  • JetRichardLee1
  • JetRichardLee1
  • 2017年03月16日 09:48
  • 319

【BZOJ2120】数颜色,带修莫队

翘文科课到机房来_(:зゝ∠)_
  • xym_CSDN
  • xym_CSDN
  • 2016年09月08日 09:28
  • 812

支(zi)持(ci)修改的莫队算法

Preface相信大家对O(n32)\mathrm O(n^{\frac{3}{2}})离线解决序列问题莫队算法都不陌生,在这里我要介绍一下能够兹瓷修改操作的莫队算法。Algorithm分块大小SS为...
  • a_crazy_czy
  • a_crazy_czy
  • 2016年06月01日 12:51
  • 2964

【模板】带修改莫队

什么是莫队算法 我们有时遇到一些询问不满足区间加减法,不能用线段树等数据结构维护的问题(如区间众数问题)。可以采用离线的方式处理询问,减少需要更改的次数,这就是莫队算法的思想。 莫队算法其实是对分...
  • zP1nG
  • zP1nG
  • 2017年09月09日 18:48
  • 226

莫队算法详解

莫队算法详解 本文翻译自MO’s Algorithm (Query square root decomposition),作者anudeep2011,发表日期为2014-12-28。由于最近碰到一些莫...
  • hnshhslsh
  • hnshhslsh
  • 2016年01月26日 00:13
  • 1632

莫队(支持修改)算法

莫队算法是个很好玩的东西,代码复杂度直降! 莫队算法可以适应一些可以从i直接转移到(i+1)的题目的离线算法,莫队算法把每个询问看成再二维平面上的点, 要使我暴力执行的次数尽量的少,顺序肯定是二维曼...
  • HOWARLI
  • HOWARLI
  • 2016年07月13日 21:51
  • 530
收藏助手
不良信息举报
您举报文章:莫队详解(先别看,有坑)
举报原因:
原因补充:

(最多只允许输入30个字)