Skip to content

高维前缀和 笔记 ​

你知道学完一个东西不写笔记会有什么后果吗?——直接失忆。

一、高维前缀和 ​

考虑求二维前缀和,除了传统的容斥方法,还可以这样:

cpp
// 考虑第一维
for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) // 每个点加上这一维上个点的和
        a[i][j] += a[i - 1][j];
// 考虑第二维
for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) // 每个点加上这一维上个点的和
        a[i][j] += a[i][j - 1];

考虑这份代码是在干什么(如注释所示)。

因此,求高维前缀和可以:

  • 考虑每一个维度。
  • 所有点加上这个维度上个点的信息。

二、SOS DP ​

1. 子集 ​

对于每一个状态 s∈[0,2n),我都希望求出他的所有子集的相关信息。事实上可以把 s 看成一个 n 维前缀和,每一维的边长只有 2,那么他的所有子集,就是相当于求他的前缀和。时间复杂度 O(n×2n)。

2. 超集 ​

从前缀和变成了后缀和。

三、刷题总结 ​

这个东西还是要看题目才能理解。

1. AT_arc100_c [ARC100E] Or Plus Max ​

显然可以将 i|j≤K 转换为 i|j=K,再对答案求前缀和。i|j=K⇒i⊂K,j⊂K。要 Ai+Aj 最大,就是要下标是 K 的子集的数中,找到最大的两个数。设 fK 表示这个东西,高维前缀和即可。

2. CF165E Compatible Numbers ​

x&y=0⇒x⊂y―,设 fx 表示数 x 的子集中一个存在的数,高维前缀和即可。查询 x 就查询 fx―。

3. CF449D Jzzhu and Numbers ​

ai1&ai2&…&aik=x⇒∀p,x⊂aip。设 fx 表示选择若干个数按位与得到 x 的方案数。看似只要求 x 的高维后缀和就好了,但实际上可能选出来的数按位与之后还是 x 的超集,所以 fx 实际是选择若干个数按位与至少是 x,那么容斥一下就好了。由于最后只要求 f0,对 x 中 1 的个数进行容斥即可。即设 gi 表示按位与出来至少有 i 个 1 的方案数。

4. P6442 [COCI 2011/2012 #6] KOŠARE ​

看数据范围,玩具种类很小,直接对每个箱子有的玩具状压,选出来之后要包含所有的玩具,那么就是选择的箱子按位或后全部是 1。设 fx 表示选择若干个数按位或得到 x 的方案数,高维前缀和,和上一题同理容斥。

5. CF1208F Bits And Pieces ​

考虑从高到低贪心确定答案每一位能否为 1,假设当前可能的答案是 x,那么由于是或,可以让 ai 贡献其中的 y⊂x,让 aj&ak 贡献其中的 z⊂x(y|z=x)。设 fx 表示只选择一个数 ai 满足 x⊂ai,最小的下标 i。设 gx 表示选择两个数 aj,ak 满足 x⊂aj&ak⇒x⊂aj∧x⊂ak,下标 j,k 的最大值。做一次高维后缀和。O(log⁡V) 枚举每一位,O(2log⁡V=V) 分配 y,z。总时间复杂度 O(n+Vlog⁡V)。

最近更新