B.Blocks
题意:
平面上有 n 个方块,
给出左上右下角坐标, (x1, y1), (x2, y2)
不断重复以下操作
随机选任意一个 (可能重复选同一个)
将该方块涂黑
一直操作直到 [0, 0] × [W, H]
的区域被完全涂黑
求操作期望次数
(n ≤ 10, x, y, W, H ≤ 1e9)
解析:
n 很小, 容易想到状压 dp
定义 dpS →
从状态 S 到完全染黑的期望次数,S 中的 1 代表该矩形选过
期望 dp 方程化简
若染色已经完成, 则期望步数为 0, dpS = 0
选到已选过的矩形, 概率 , 形成环,
移项即可解决
令 S 为当前的状态, x 为
S 中 1 的个数
判断已经全部染黑
提供两种方法
1. 二维离散+二维差分:
不难发现大部分区域都是无用的, 对 x, y 轴分别离散即可
离散后大概只有 21 行/列
现在想要 [x1, y1] × [x2, y2]
的矩形区域 +1
离散后范围较小, 可以直接暴力对矩形区域 +1
之后暴力 ...
XCPC
未读HDU
25春季联赛 - 0 - 1007
题意:
给定长度 n 的数组 a,
定义 [l, r] 价值为
⨁i = lrai ⋅ (r − l + 1),
定义 f(a) 为数组
a 划分后的最大价值和,
求
(n ≤ 2e5, 0 ≤ ai < 1024)
解析:
很容易想到 n2
dp
pre
为前缀异或数组
定义 dpi
→ 用前 i 个元素能得到的最大价值
转移方程:
复杂度不可接受, 尝试优化
我们拆开式子:
1.先考虑一个更简单的式子: 观察左侧部分: dpj − (prei ⊕ prej) ⋅ j
当我们在 j 时, 未知量只有
prei
定义 g(x) → max{dpj − (x ⊕ prej) ⋅ j}
我们遍历到 j 时, 对所有可能的
x 的值进行预处理
转移方程:
由 ai < 1024
可知 x < 1024
预处理时间复杂度 O(1024)
转移复杂度 O(1)
总时间复杂度 O(1024 ⋅ n)
2.让我们回到原式 类似地
定义 g( ...
XCPC
未读CF1887D
题意:
定义一个数组是好的,仅当其可分割成两个非空数组,使得左边元素都小于右边元素
即满足 max(al…ak) ≤ min(ak + 1…ar)
给定排列,q次查询,问 [l, r] 的子数组是否是好的
(n, q ≤ 3e5)
解析:
固定 l,r,若枚举 k,左右两侧都是单增,因此整体不存在单调性
法 1:
二维离线
从值考虑
我们考虑左侧区间中的最大值,
若 ai
成为最大值,我们记 i 左侧第一个大于 ai 的元素位置为
l1,则有限制 l1 < L ≤ i
我们记 i 右侧第一个大于 ai 的元素位置为
r1,记 r1 右侧第一个小于 ai 的元素位置为
r2,则有限制 r1 ≤ R < r2
这样的 [L, R] 就是左侧以 ai
为最大值的好区间
( i 左右找 > ai
的第一个位置是很典的问题,可以用单调队列,笛卡尔树,按值枚举甚至还可以用
set )
也就是,以 ai
为最大的合法情况落在矩阵 L ∈ [l1 + 1, i], R ∈ [r1, r2 − 1 ...
前言
在不要求实时更新数组的情况下,差分是非常有用思想。相较于一阶差分的区间加,二阶差分可以进行更复杂的操作,比如将一个区间加上等差数列,或是一次性对多个特殊区间进行区间加操作。
二阶差分是一阶差分的扩展,相应的,还有更高阶数的差分,可以用来区间加多项式
前置知识
一阶差分
一阶差分可以 O(1)
实现区间加操作,最后 O(n) 求出原数组。如要求
al…ar
都加 v,则diff[l]+=v, diff[r+1]-=v即可。
同理,在二维的情况下也可以 O(1) 实现矩形区域加,最后 O(nm)
求出原数组。具体来说若 [x1, x2] × [y1, y2]
的二维区域都加 v,则diff[x1][y1]+=v, diff[x2+1][y1]-=v, diff[x1][y2+1]-=v, diff[x2+1][y2+1]+=v即可。
二阶差分
若每次操作要将 [l + xd1, r + xd2]
这样的一堆区间每个区间都加 v,一阶差分每次操作时间复杂度 O(x)。对于这样的问题,二阶差分可以优化为
O(k + n),k
为操作次数。
我们先考虑一个 ...
前置知识 - 状压 dp:
(220 ≈ 1e6,317 ≈ 1e8)
1. SOS DP - 子集和 dp:
每个集合有一个权值f(S),我们想求集合 S 所有子集的权值和 dpS,即
(注意:每个子集有且仅有一次贡献)
若暴力求解,枚举S,然后枚举sub,时间复杂度 O(3n)
SOS dp:先枚举位,让所有集合逐位转移,时间复杂度 O(n ⋅ 2n)
[理解参考]
参考代码
123456789// f(S) 权值数组已知dp = f; // 赋初值for(int p=0; p<20; p++){ // 先枚举位 for(int S=1; S<=full; S++){ // 再枚举所有集合 if(S >> p & 1){ dp[S] += dp[S ^ (1 << p)]; } }}
2. 子集划分 dp
时间复杂度 O(3n)
大致操作是枚举 mask,然后枚举子集 S,和补集 T
然后 merge(S, T)
和区间 dp 一 ...
前置知识-容斥定理:
将事件 A,表示成多个子事件 A1, A2...Ak 的并集,不要求事件互斥,即 ⋃Ai = A
容斥定理,可以让我们用这些子事件的交集计算整个事件
1. 两集合的简单容斥
2. 更一般的容斥定理
3. 子集容斥-子集反演
为某集合,若两个函数满足如下关系:则其逆运算为:
洛谷P10580
题意
长度为 n 的序列 a, gcd (a) = x, lcm(a) = y, 求序列方案数
解析
对于x,y,由唯一分解定理,我们可拆解成如下形式
不同质因子相互独立,考虑研究某个质因子,假设是 p1
分解 ai = p1ki1p2ki2p3ki3...
因为gcd (a) = x,我们有 min ki1 = c1
因为lcm(a) = x,我们有
max ki1 = e1
也就是所有序列中所有数,都要满足,质因子的幂,且至少存在一个数的幂是 c1,至少存在一个数的幂是
c2
设 t = y/x,分解
t = p1k1p2k2p3k3...
对于某种质因子,我们等价转化成如下 ...
二维前缀和是一维前缀和的扩展,三维前缀和则是二维的基础上再加一维
三维前缀和
求三维前缀和数组,可以分别对 x,y,z 维进行求和。二维同样也可以分别对
x,y 维进行求和,只是我们很少这样去做。
具体来说 :
1234567891011121314for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)for(int k=1; k<=h; k++)mat[i][j][k] += mat[i-1][j][k];for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)for(int k=1; k<=h; k++)mat[i][j][k] += mat[i][j-1][k];for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)for(int k=1; k<=h; k++)mat[i][j][k] += mat[i][j][k-1];
还有一种容斥的方法也可以求这个,不过比较复杂 :
123456789101112 ...










