莫队

0. 离线与在线

在线算法一般是 预处理 + 输出。离线算法一般是 输入 + 一起处理。

一个典型的例子是求 LCA,有两种方法:倍增、Tarjan。

倍增是预处理所有节点的 \(2^k\) 祖先,然后每次暴力跳。

Tarjan 是输入完所有数据,再全部放在树上处理。

1. 普通莫队

1.1 莫队主体思想

如果 \([l,r]\) 能够 \(O(1)\) 扩展到 \([l-1,r],[l+1,r],[l,r-1],[l,r+1]\)且不强制在线,那么可以使用分块。

莫队 = 分块 + 暴力 = 优雅的分块 = 优雅的优雅暴力。

1.2 分块部分与查询顺序

为了保证时间复杂度,需要对原序列进行分块。

定义一次询问的块在 \(\left\lfloor\dfrac{l}{kc}\right\rfloor\)

我们对询问的定义是这样的:

struct ask{
	int l,r,id;
	bool operator < (const ask A) const {
		if(l/kc!=A.l/kc) return l<A.l;
		if((l/kc)&1) return r<A.r;
		return r>A.r;
	}
};

如果两个块不在一块,考虑按左端点排序。这样可以保证 \(l\) 大体上从左往右递增。

如果两个块在一块,使用奇偶性排序。

详见 oi.wiki

1.3 处理答案

处理答案的常用方法是从已知区间 \([l,r]\) 扩展到 \([L,R]\)。这一部分较简单:

for(int i=1;i<=q;i++)
{
  ask q=b[i];
  while(l>q.l) update(--l,1);
  while(r<q.r) update(++r,1);
  while(l<q.l) update(l++,-1);
  while(r>q.r) update(r--,-1);
  // 处理答案
}

update 部分较为灵活:如果 \(x\) 位置出现/失去,会对答案造成怎样的影响。

1.4 时间复杂度分析

左端点在每个块时间复杂度为 \(O(n)\)(左端点移动具有单调性),共 \(O(\sqrt n)\) 块,时间复杂度 \(O(n\sqrt n)\)

右端点在每个块时间复杂度为 \(O(n)\),共 \(O(\sqrt n)\) 个块,时间复杂度 \(O(n\sqrt n)\)

所以莫队时间复杂度 \(O(n\sqrt n)\)

1.5 求区间和

经典莫队题?

考虑移动一次区间对答案的贡献,update 如下:

void update(int pos,int Sign)
{
    Count+=Sign*a[pos];
}

1.6 数列找不同

经典莫队题。

考虑数当前区间的颜色数,update 如下:

void update(int pos,int Sign)
{
	cnt[a[pos]]+=Sign;
	if(cnt[a[pos]]==1&&Sign==1) Count++;
	if(cnt[a[pos]]==0) Count--;
}

1.7 小 Z 的袜子

经典莫队题。

我们知道一种颜色的袜子的贡献为 \(\dfrac{1}{2}cnt(cnt-1)\),所以 update 如下:

void update(int pos,int Sign)
{
	Count-=cnt[a[pos]]*(cnt[a[pos]]-1)/2;
	cnt[a[pos]]+=Sign;
	Count+=cnt[a[pos]]*(cnt[a[pos]]-1)/2;
}

2. 带修莫队

2.1 不能带修?时间维!

从普通莫队到定义 \([l,r,time]\)

如果 \([l,r,time]\) 可以 \(O(1)\) 变换成 \([l-1,r,time],[l+1,r,time],[l,r-1,time][l,r+1,time],[l,r,time-1],[l,r,time+1]\),那么可以使用带修莫队。

带修莫队的时间复杂度一般为 \(O(n^{2/3}m^{2/3}t^{1/3})\) 也就是常说的 \(O(n^{5/3})\)

2.2 带修莫队

第一关键字是左端点所在块,第二关键字是右端点所在块,第三关键字是时间。

块长设置 \(O(n^{2/3})\)

2.3 【模板】树状数组

2.4 「国家集训队」数颜色/维护队列

3. 二维莫队

3.1 二维莫队的原理

二维莫队的思路同带修莫队。

考虑维护 \([l_1,r_1,l_2,r_2]\),如果能 \(O(1)\) 转移 \([l_1-1,r_1,l_2,r_2],[l_1+1,r_1,l_2,r_2],[l_1,r_1-1,l_2,r_2],[l_1,r_1+1,l_2,r_2],[l_1,r_1,l_2-1,r_2],[l_1,r_1,l_2+1,r_2],[l_1,r_1,l_2,r_2-1],[l_1,r_1,l_2,r_2+1]\),那么可以使用二维莫队。

Q:上面是一托啥啊?

A:简单来看就是将一个位置 \(\pm 1\)

3.2 二维莫队的块长

块长 \(S=n\times q^{\frac{1}{4}}\)。很容易发现这个值可能为 \(0\),此时取 \(1\) 即可。

时间复杂度 \(O(n^2q^{\frac{3}{4}+q\log q})\)

4. 树上莫队

5. 回滚莫队

posted @ 2024-11-23 15:37  sLMxf  阅读(20)  评论(0)    收藏  举报