莫队 + 带修莫队

Posted q1204675546

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了莫队 + 带修莫队相关的知识,希望对你有一定的参考价值。

莫队其实就是一个带优化的暴力,通过将区间询问按一定规则进行排序,从而优化过程,求出答案。

 

 

举一例子:(例子不具备权威性,只是让读者了解莫队是干啥的)

 

/*
输入四个区间

1  4     初始条件,L= R = 0,     将R遍历到4    需要走4步   L走一步,共5次   
4  8   继承上一次 L 和 R 的值,L从1到4   需要3次,R从4到8,需4次,  总计8次     
2  9   同理继承,   L回退2次,  R前进一次                        总计3次      
1  2   同理,L回退1次,R回退7次                                 总计8次                          


如果直接暴力,计算机将要计算     5+8+3+8=24次


如果将询问进行排序呢?假设排列成如下模样:

1 2              总走3次
1 4           总走2次
2 9           总走6次
4 8            总走3次  


全局总走3+2+6+3=14次,这相差是不是很大?这也是莫队的思想,将暴力优化。   
*/

 

 

 

至于如何将询问排序,证明就有一点烦恼,直接说结论:

可以借助分块思想,假设总区间为n,那么每一块区间长度应趋近于    n^(2.0/3)

可以将询问中的  L或者是 R,按其所在块的编号,  从小到大排序,然后再慢慢暴力。。。这就是莫队,说一下莫队的数据极限是     5e5,超过1e7,则需要另谋高就。

 

 

 

 

附上一题:P1494 [国家集训队]小Z的袜子

 

对于该题,有着优化操作,也是组合公式的直接约分简化。

方案1

    

技术图片

 

 

方案2:

 

技术图片

 

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<stack>
#include<map> 
#include<algorithm>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define Mem0(x) memset(x,0,sizeof(x))
#define Mem1(x) memset(x,-1,sizeof(x))
#define MemX(x) memset(x,0x3f,sizeof(x))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f;
const double pi=acos(-1.0);


const int N=500010;
int B,ans[N][5],fz,fm,len,n,m,col[N],cnt[N];
struct s
	int l,r,id;
	bool operator < (s&b)
	
		return l/B==b.l/B?r<b.r:l<b.l;
	
q[N];    

void init()

	len=fz=fm=0;
	memset(cnt,0,sizeof(cnt));
	cin>>n>>m;		B=sqrt(n);
	for (int i=1;i<=n;i++)
		cin>>col[i];
	
	
	for (int i=0;i<m;i++)
		cin>>q[i].l>>q[i].r;
		q[i].id=i;
	
	sort(q,q+m);

bool cmp(s&a,s&b)

	if (a.l/B==b.l/B)
		return a.l>b.l;

void add(int x)

	fz+=cnt[x];
	cnt[x]++;
	fm+=len;
	len++;

void delect(int x)

	cnt[x]--;
	fz-=cnt[x];
	len--;
	fm-=len;

int main()

	init(); 
	int l=1,r=0;
	for (int i=0;i<m;i++)
		if (q[i].l==q[i].r)
			ans[q[i].id][0]=0;
			ans[q[i].id][1]=1;
			continue;
		
		while (l<q[i].l)
			delect(col[l++]);
		
		while (l>q[i].l)
			add(col[--l]);
		
		while (r<q[i].r)
			add(col[++r]);
		
		while (r>q[i].r)
			delect(col[r--]);
		
		int tmp=__gcd(fz,fm);
		ans[q[i].id][0]=fz/tmp;
		ans[q[i].id][1]=fm/tmp;
	
	for (int i=0;i<m;i++)
		printf("%d/%d\\n",ans[i][0],ans[i][1]);
	
	return 0;

  

 

带修莫队就是带上了修改。。。。    (待更新)

 

带修莫队  =  莫队  +  修改  + 保留旧版本信息

以上是关于莫队 + 带修莫队的主要内容,如果未能解决你的问题,请参考以下文章

莫队 + 带修莫队

bzoj 2120 数颜色 (带修莫队)

带修莫队

2120: 数颜色(带修莫队)

Machine Learning(带修莫队)

带修莫队板子