杂题选记

P13357

难度:绿

不会。那咋办。
gcd 问题考虑枚举答案。枚举答案 \(w\),找到 \(\le R\) 的最大的 \(w\) 的倍数 \(R - (R\bmod w)\),只需判断 \(R - (R\bmod w) - w\) 是否 \(\ge L\)。正确性显然。
考虑怎么优化,将 \(R - (R\bmod w)\) 写成 \(\lfloor \frac{R}{w} \rfloor w\),也就是判断 \(\lfloor \frac{R}{w} \rfloor w - w\) 是否 \(\ge L\)。注意到 \(w\) 较大时,\(\lfloor \frac{R}{w} \rfloor\) 数量极少,是根号级别的。考虑枚举 \(t = \lfloor \frac{R}{w} \rfloor\),需要找到 \(w(t - 1)\) 的最大值,也就是使 \(w\) 最大,令 \(w = \frac{R}{t}\) 即可。那么做完了。时间复杂度 \(O(\sqrt R)\)。

P10849

难度:绿

急哭了。
对于 \(i\),显然是贪心往 \(1\sim i-1\) 放,同时选择等级尽量大的。容易用栈维护。

P9565

难度:绿

考虑什么时候答案满足 \(\ge V\):存在二进制位 \(b\),满足答案高 \(b-1\) 位与 \(V\) 相同,第 \(b\) 位 \(V\) 为 \(0\),答案为 \(1\)。
考虑怎么维护这个东西。遍历每一个二进制位 \(b\),初始化并查集,如果 \(V\) 当前位为 \(1\),把边权这一位为 \(0\) 的边都扔掉。否则如果为 \(0\),边权这一位为 \(1\) 的边就可以合并。对于每个 \(b\),如果 \(u,v\) 在当前层的并查集里在同一连通块,答案为 Yes。
如果每一层都不在,就为 No。

CF506D

难度:青

对每种颜色根号分治。
把相同颜色的边摘出来,如果个数 \(> \sqrt m\),这类颜色至多 \(\sqrt m\) 个,那么可以冰茶鸡维护连通块扫一遍询问,\(O(q\sqrt m)\)。否则个数 \(\le \sqrt m\),冰茶鸡维护,枚举所有点对算贡献,所有颜色点数的平方和 \(\le O( n\sqrt n)\)。于是就是 \(O(q\sqrt m\log q + n\sqrt n)\)。注意没有算冰茶鸡的常数。

CF1221F

难度:青

简单题。写出柿子之后容易扫描线维护。

P5679

难度:青

考虑三个数 \(a_i,a_j,a_k\),如果存在 \(a_i - a_j = a_k - a_i\),那么 \(a_k = 2a_i - a_j\),由于非负不妨转化 \(a_k + V = 2a_i - a_j + V\),维护 bitset \(f,g\),\(f\) 记录 \(a_k+V\),\(g_x\) 记录 \(V - a_j\)。
假设当前在加入 \(x\),如果 \(f_x=1\) 这组询问就有解。否则 \(f\) 对 \(g\) 左移 \(2x\) 的结果进行按位或,再把 \(g\) 的第 \(V - x\) 位设为 \(1\)。正确性显然。

bool ok = false; 
for (ll i = 1; i <= n; ++ i ) {
	ll x; cin >> x; 
	if (f[V + x]) ok = true; 
	f = f | (g << (x << 1));  
	g.set(V - x, 1); 
}
cout << (ok ? "YES\n" : "NO\n"); 

P6241

难度:青

显然我们可以轻松得到 \(1,1,2,4,8,16,32,\cdots\),你考虑把其中 \(1\) 个减 \(1\),序列变成 \(1,1,2,3,7,14,28\cdots\),手玩得到规律,对 \(a_{n-i-1}\) 减少 \(1\),那么 \(a_n\) 减少 \(2^i\),那么找到第一个比 \(q\) 大的 \(p = 2^i\),把 \(p - q\) 二进制分解即可。

P16541

难度:蓝

容易会掉 \(O(nq)\)。考虑 dp 的本质是啥,本质上我们在维护最大值、次大值 \((A,B)\),每次给次大值加上 \(w_i\),如果加完 \(A < B\) 了就交换一下。那么有一个结论是 \(A + B =\sum w_i\),不妨记为 \(S\)。
注意到值域很小,\(w_i\le 50\),我们来考虑维护 \(A - B\) 的差,遇到一个 \(w_i\) 就 \(|A-B| \to |A-B-w_i|\)。由于操作具有可合并性,使用 sgt 维护。具体对于每个区间,维护 \(50\) 个节点,每个节点的值表示最初为 \(x\),经过当前区间会得到的值。pushup 的时候先走右区间,再走左区间。

void pu(ll k) {
	for (ll i = 0; i <= 50; ++ i ) 
		tc[k][i] = tc[k << 1][tc[k << 1 | 1][i]]; 
}

P15255

难度:蓝

\(O(2^nn^3)\) 可以通过。
考虑熔池,考虑一组 \((x,y,z)\),有一下几种情况:

  • \(x\) 为 \(1\) 得分加 \(1\)。
  • \(x,y\) 为 \(1\),得分减 \(1\)。
  • \(x,z\) 为 \(1\),同上。
  • \(x,y,z\) 为 \(1\),得分多减了,要加 \(1\)。

然后跑 sosdp 就完了。时间复杂度 \((n2^n + K)\)。

P14402

难度:蓝

神秘最短路。你考虑当前在 \((x,y)\),下一步能向哪移动??

  • 向上下左右走一步,到最远的冰块。
  • 走两步走到相邻节点。

直接建图做就是对的。证明考虑不合法的路径都不优。参考题解:

若考虑操作一所生成的冰块,直接返回等价于操作二,若绕一圈回到起点(例如先向右滑动到冰块前,并在起点生成一个冰块,再依次往下左上回到最初的位置)代价至少为 \(3\),这一步劣于直接向下移动一格,代价为 \(2\)。
若考虑操作二所生成的冰块,直接前进(例如先向右,左滑动,移动到右边一格,再继续向右滑动)劣于只执行一步操作一,若是继续绕一圈再回到原位,步数显然只会更多。

P5228

难度:青

考虑 dp,\(f_i\) 表示面值最大值为 \(i\) 时的最小代价,转移就枚举 \(i\) 的倍数作为最大值,更新减少的贡献。

P7768

难度:青
考虑对每个深度进行维护。维护每个深度点权的异或和。
对每个 dfs 序维护一珂主席树,查询的时候使用 \(ed_x\) 版本的主席树异或掉 \(st_x-1\) 版本的主席树,注意主席树上维护的是每个深度的点权异或和。
不会离线做法,跑路了。

P3200

难度:绿

考虑我们每次插数,当前在决策要放在奇数位还是偶数位。那么要求偶数位的个数 \(\ge\) 奇数位的个数,也就是入栈个数 \(\ge\) 出栈个数,即卡特兰数。

9.23 A

嘻嘻。

显然可以二分。考虑二分到答案为 \(v\),那么中位数 \(\ge v\) 当且仅当我们可以选出 \(\ge (n+1)/2\) 个 \(\ge v\) 的数。那么随便做。

9.23 B

做麻烦了。
考虑看成线段,分讨交换之后的贡献。代码不超过十行。

P9180

急。

显然有个暴力 dp,\(f_{i,l,r}\) 表示考虑前 \(i\) 个询问,剩下区间 \([l,r]\) 是否可行。转移容易做到 \(O(n^3)\),获得 \(21\) 分。
显然对于相同的 \(l\),我们希望右端点越大越好,把这个东西放到状态里。\(f_{i,l}\) 表示考虑前 \(i\) 个询问,左端点为 \(l\),右端点的最大值。转移的时候你考虑从前 / 后缀转移。

  • 前缀。右端点不变,考虑如果 \([l-d+1,l]\) 合法,那么可以从 \(f_{i-1,1...l-d}\) 转移,可以维护前缀最大值做到 \(O(1)\) 转移。
  • 后缀。比较麻烦,对于任意右端点 \(r\) 满足 \([r-d+1,r]\) 合法,可以从 \(r-1\) 转移。维护 \(R_x\) 表示 \(x\) 及之前能满足这个要求的最大值。轻松维护 \(R_x\) 可以做到 \(O(1)\) 转移。

总的时间复杂度 \(O(n^2)\)。

P7362

感觉不是很难的题。赛时没做多久,获得了可观的分数就跑路了。现在看来正解也是不难的。

  • \(S = 1\),手玩容易知道对相邻数异或操作 \(3\) 次可以交换。容易做到 \(K = 3n(n-1)/2\),可以获得可观的分数。我们现在做的是冒泡,考虑变成插入排序。每次考虑当前序列的最大值,假设序列当前 \(\{a,b,c,d,e\}\),转成 \(\{a\oplus b,b\oplus c,c\oplus d,d\oplus e,e\}\),如果最大值是 \(c\),再转成 \(\{a\oplus b,b\oplus c,c\oplus d,c\oplus e, c\}\),这样 \(c\) 就被放到了最后,最后处理 \(c\) 之前的变成 \(\{a\oplus c,b\oplus c, c\oplus d,c\oplus e, c\}\)。这样 \(c\) 的影响被消去(下一次异或会把 \(c\) 消去)。继续处理前面的数即可。操作数大概 \(O(n^2)\)。
  • \(S = 2\),赛时没仔细想。对于每一位分别考虑,如果存在一个 \(1\),显然可以放在最后。具体如果存在某个 \(i\) 满足 \(A_{i,bit}=1\),若 \(A_{i+1,bit}=1\) 可以消掉,否则可以通过两次异或消掉,转移到 \(i+1\)。那么如果存在 \(1\) 只会被放在最后。考虑下一位时就可以把上一位末尾的数扔掉。

P7168

神笔数学题。

一个经典结论是按题目中连对角线的方法,会划分出若干个三角形。
考虑 \(0\) 没出边的情况,这个时候显然答案是 \((0,n-1)\)。否则我们只关心与 \(0\) 相关画出来的三角形。依次询问 \([1,n-1]\) 与 \(0\) 是否有边,以及相邻边的底边即可。

P6298

很好的熔池。
记 \(g_i\) 表示选 \(k\) 个数,\(\gcd\) 是 \(i\) 的倍数的方案数。你维护 \(f_i\) 表示原序列中能被 \(i\) 整除的数的个数,显然 \(g_i = \binom{f_i}{k}\)。考虑答案怎么求,从后往前枚举,维护 \(t_i\) 表示 \(i\) 的真实答案,初始 \(t_i = g_i\),熔池一下得到 \(t_i = g_i - t_{2i} - t_{3i} \cdots\) 即可。

10.1 B

不会做绿题。那咋办。
考虑一个简单的转化,你发现答案可以从大矩形一直异或下去得到,考虑去加速这个过程。做二维前缀和 \(p_{i,j}\) 表示矩形 \([1,i] \times [1,j]\) 的异或和。考虑正在计算答案 \([a,c] \times [b, d]\),第 \(k\) 个矩形的答案 \(p_{c-k,d-k} \oplus p_{a+k-1,d-k} \oplus p_{c - k,b+k-1} \oplus p_{a+k-1,b+k-1}\)。记边界 \(T = \min(\lfloor \frac{c-a}{2}\rfloor,\lfloor \frac{d-b}{2}\rfloor)\),即计算 \(k \in [0, T]\) 的异或和的异或和。考虑拆开:

  • $ A = \oplus_{k=0}^T p_{c-k,d-k}$
  • $ B = \oplus_{k=0}^T p_{a+k-1,b+k-1}$
  • $ C = \oplus_{k=0}^T p_{a+k-1,d-k}$
  • $ D = \oplus_{k=0}^T p_{c-k,b+k-1}$

容易维护。

10.1 C

棋差一招。
记 \(lf_i\) 表示 \(i\) 子树内叶子个数,\(f_i\) 表示当前在 \(i\),走遍 \(i\) 子树内叶子但无功而返的最小代价,\(g_i\) 表示当前在 \(i\),在子树内抓到小偷的期望时间(\(g_1\) 即为答案)。

  • \(lf_i\) 转移显然。
  • \(f_i = \sum_v (f_v + 2)\)
  • \(g_i = \sum_v \frac{lf_v}{lf_i}(1 + g_v + \sum_{j < i}f_j+2)\)

然后考虑要按什么顺序决策。经典的邻项交换,注意到只有第三者里的 \(lf_v\sum_{j < i} f_j+2\) 与顺序相关,按 \((f_a+2)lf_b < (f_b + 2)lf_a\) 排序即可。
可以通过没有监控的分数。有监控呢?有监控的位置 \(f_i = 0\) 即可。第三项使用前缀和优化可以做到 \(O(n)\)。

P13785

\(O(n^2)\) dp 是容易的,\(f_{i,j}\) 表示末尾是 \(a_i\),上一位是 \(a_j\),但是没啥前途,考虑优化。
一个结论是,记答案的下标序列为 \(b_i\),注意到 \(b_i\) 和 \(b_{i+1}\) 之间至多只会有 \(4\) 种与 \(b_i,b_{i+1}\) 不同的颜色出现,那么有效的状态只有 \(O(nk)\) 种,其中 \(k = 4\)。

P1357

好题。
考虑暴力 dp 怎么做。\(m \le 5\) 显然状压。枚举每一种状态为起始做一遍,即初始 \(f_{i,sta} = 1\),\(f_{n,sta}\) 即为答案。
转移把最高位去掉,判断填 \(0/1\) 是否合法即可。时间复杂度 \(O(n2^{2m})\)。
考虑使用矩阵快速幂优化。\(T_{i,j}\) 表示状态 \(i \to j\) 的方案数。记 \(T' = T^n\),答案即为 \(\sum_i T'_{i,i}\)。

P12966

模拟赛遇到不会做,菜飞了。

很好的 trick。显然要在 \(m_i \mid m_j\) 上做文章。记最小的 \(m\) 为 \(m_0\),把所有数 \(m \to \frac{m}{m_0}\),按 \(m\) 小到大排序。
容易想到把 \(m\) 相同的放在一起考虑。最小的 \(m_1 = 1\),由于除了 \(m_1\),剩下的 \(m\) 都满足 \(m_2 \mid m\),所以背包里 \(m \bmod m_2\) 的空间只能放 \(m_1\),贪心放置完毕后,如果还有剩余,直接压成若干个质量为 \(m_2\) 的物品即可,注意如果有剩余要用价值为 \(0\) 的物品填充。

P15890

挂几个定义:

  • 图的最大匹配 \(M \subseteq E\):任意两边没有公共端点的最大匹配,即最大边独立集。
  • 图的最大独立集 \(S \subseteq V\):任意两点间没有边。
  • 图的最小顶点覆盖 \(C \subseteq V\),每条边至少有一个端点属于 \(C\)。

对任意图,有 \(S + C = V\)。
在二分图里,由于 \(M = C\),可以得到 \(S + M = V\)。
然后注意,在二分图里我们可以轻易求出最大匹配所以三个都能求。在一般图里,最大匹配可多项式求,但另外两个是 NP-Hard。

在本题里,先把那些肯定不能放学生的位置扔掉(禁止的或者旁边有 \(2\) 的)。对于剩下的学生,我们把它往上下左右连边,然后就是求解最大独立集。然后重要的 trick 是,网格天然是一个二分图(按 \(x+y\) 的奇偶性划分),跑最大匹配在减掉即可。

P14662

不会做,嘻嘻。
记 \(f(i) = 1 \oplus 2 \oplus \cdots n - 1 \oplus n\),赛时打表发现只可能等于 \(0/1/n/n+1\) 就没继续想了。实际上这个是很有用的。大力分讨:

  • \(n\bmod 4 = 3\),此时 \(f(n)=0\)。容易想到分成两组,一组为 \(n\),剩下放另一组。组内不连边,不同组连边。
  • \(n\bmod 4 = 1\),此时 \(f(n)=1\)。分成三组,\(\{1\},\{2,3\}\) 和 \(\{4\cdots n\}\),容易证明是对的。
  • \(n\bmod 4 = 0\),此时 \(f(n)=n\)。分成三组,\(\{n\},\{lowbit(n),n-lowbit(n)\}\) 和剩下的。注意如果 \(lowbit(n)=n\),即 \(n = 2^k\) 时无解。因为最高位那个 \(1\) 怎么都消不掉。
  • \(n\bmod 4 = 2\),此时 \(f(n)=n+1\)。分成三组,\(\{1,n\},\{2,n-1\}\) 和剩下的。

注意判掉 \(n=1,2\),然后就通过了。

P12701

不会,嘻嘻。
拆成 \(km\) 次操作。由于每个数最多只能加 \(m\) 次,总有一个前缀被填到上限,后面的会被填平到某个数,于是可以二分这个数,判断总次数是否 \(\le km\) 即可。注意如果有剩下的次数要继续操作。

P9525

好题哇。
考虑每次分别取出三个里面最大的,如果满足要求互不相同就直接输出。否则肯定存在一个 \(i\) 使得它的某两项同时为最大值,容易证明 \(i\) 肯定不能被选,直接标记扔掉即可。实现拿三个堆即可。

10.10 B

。
如果一个数 \(x\) 能被合并,必然由一奇一偶合并。偶数无法合并,因此偶数很重要。枚举每个偶数,判断与它相邻的奇数是否存在 / 能否合并出来。注意如果存在肯定先用存在的而不是合并的是更优的。由于只会递归 \(O(\log V)\) 层,时间复杂度 \(O(n\log n\log V)\)。

10.10 C

好题。
假设当前在求解 \(x\),位置为 \(p\)。中位数问题考虑弄个 -1/0/1 序列 \(c\) 出来,分别表示 \(<x,=x,>x\)。那么合法区间就满足包含 \(p\) 且区间和为 \(0\)。记 \(c\) 的前缀和为 \(s\),维护 \(s\) 的区间前缀最值和后缀最值。因为值域连续,当且仅当前缀、后缀值域有交时合法。当然还要判断全在左 / 右的情况。这个序列 \(c\) 可以 \(O(1)\) 维护。时间复杂度 \(O(n\log n)\)。

P4563

神秘。
考虑计算区间 \(f(l,r)\) 的答案。显然 \(r\) 要选,那么会有若干个亭子是 \(r\) 能看到的,不妨记为 \(p_1,p_2,\cdots ,p_k\),那么区间 \([p_i+1,p_{i+1}-1]\) 无法被 \(r\) 看守,需要再安排保镖去看守,容易证明看守位置不超过 \(p_{i+1}\)。那么 \(p_{i+1} / p_{i+1}-1\) 肯定会放。\(f_{l,r} = \sum \min(f(p_i,p_{i+1}),f(p_i,p_{i+1}-1))\)。那么可以固定 \(r\),\(l\) 从 \(r\) 开始扫,动态维护当前的 \(p_i,p_{i+1}\) 即可。时间复杂度 \(O(n^2)\)。

P13649

\(Y_i\) 互不相同的做法。写出朴素转移方程:

\[f_i = S_i + \max_{X_j \in [X_i - E_i, X_i + E_i], Y_j \in [Y_i - E_i,Y_i]} \]

对 \(X\) 开线段树,对每个节点维护 \(\ge Y_i - E_i\) 的 dp 值的最大值。查询时在单调栈上二分即可。时间复杂度 \(O(n\log^2 n)\)。

P2218

原神题。
显然能二分。考虑当前的点集,维护 \(minx,maxx,miny,maxy\)。判断能否一个正方形覆盖,不能这个正方形的角一定是某个点。枚举四种情况爆搜即可。

P10982

骇人。
考虑熔池,\(n\) 个节点的连通图个数等于 \(n\) 个节点的图的个数减去 \(n\) 个节点不连通的图的个数。前者显然是 \(2^{n(n-1)/2}\),后者考虑枚举 \(1\) 所在连通块大小 \(k\),记 \(n\) 的答案为 \(f(n)\),显然 \(f(n) = 2^{n(n-1)/2} - \sum_{k=1}^{n-1} \binom{n-1}{k-1}f(k)2^{(n-k)(n-k-1)/2}\)。时间复杂度 \(O(n^2)\),可以使用神秘科技优化。

10.13 B

嘻嘻嘻。
考虑 dp,\(f_{i,j}\) 表示前 i 个选了 \(j\) 个。

P4933

原来时空 \(O(nV)\) 能过,这么变态。
枚举公差,考虑前缀和优化,做到空间 \(O(n + V)\),时间 \(O(nV)\)。

P13046

我宣称 \(70\) 分是容易的。
考虑朴素暴力 dp。\(f_{i,0/1}\) 表示考虑前 \(i\) 个数,最后一段合法 / 不合法。考虑 \(j\) 能向 \(i\) 转移的充要条件。
设 \(p_i\) 表示前 \(i\) 个数字组成的数字串。那么新加入的段就是 \(p_i - p_j10^{i-j}\),我们要求 \(p_i \equiv p_j10^{i-j} \pmod D\)。
如果 \(\gcd(10, D) = 1\) 是容易的,因为 \(10\) 有逆元,等价于 \(\frac{p_i}{10^i} \equiv \frac{p_j}{10^j} \pmod D\),可以使用桶来维护。
否则记 \(D = dm\),其中 \(\gcd(10,d)=1\)。\(i-j\) 较大时,有 \(m \mid 10^{i-j}\),那么需要 \(m \mid p_i\),那么问题转化成 \(\frac{p_i}{10^i} \equiv \frac{p_j}{10^j} \pmod d\)。\(i-j\) 较小时暴力即可。取阈值 \(B = 20\) 即可通过本题。

10.14 C

good problem。
考虑暴力,枚举断掉哪条边,这样每个区间的方向就确定了!!容易做到 \(O(nP)\)。
然后考虑断边的过程,容易发现修改的区间数量很少,变化很小,均摊变化量只有 \(O(P)\)。使用线段树区间加,区间查 \(> 0\) 位置的权值之和。pushup 时随便维护一下即可。

P3076

good problem。
显然 \(|S_i - T_i|\) 要加上。然后考虑多余的路程,刻画出柿子 \(|S_i - T_{i-1}|\),按 \(S,T\) 小到大排序就是对的。

P5677

sugar。
注意到所有数不相同。预处理 \(i\) 的一个 / 两个配对,记为 \((i, p)\)。那么每次就在计算满足 \(l \le i \le p \le r\) 的对数,简单二维数点。

10.15 B

good problem。
注意到两个结论即可过题。

  1. 首先就是最优解区间 \([x,y]\) 分别距离 \(l,r\) 很小,否则肯定可以继续扩展。可以证明距离不会超过 \(3\)。那么枚举 \([l,l+B]\) 作为左端点暴力即可。实际上随便取个 \(B=10\) 做到 \(O(qnB)\) 即可获得 \(60\) 分!
  2. 钦定左端点 \(l\),计算左端点为 \(l\),右端点 \(\le r\) 的答案。计算出 \([l,r]\) 三个数的出现次数 \(a,b,c\)。不妨 \(a \le b \le c\)。若 \(a < b < c\) 就是对的。否则需要从右边一直删,大力分讨一下。如果 \(a = b < c\),会一直删 \(c\) 直到 \(a=b=c\)。如果 \(a + 1< b=c\),会一直删 \(a\) 直到删到 \(b,c\)。如果 \(a+1=b=c\) 随便删一个可以转化为上述情况。如果 \(a=b=c\),如果互不相同就只能一直删,否则一定是合法或者 \(a+1 < b = c\) 的情况。任何步骤都可以 \(O(1)\)。
    那么每次枚举合法的几个左端点,右端点 \(O(1)\) 求答案即可。

10.15 C

good problem。
答案显然是某个 \(b\) 加上后缀的 \(a\)。
假设从 \(l\) 开始做,刻画出柿子 \(\min(x + S_r - S_{l-1}, \min_{i=l}^r(b_i + S_r - S_i))\)。其中 \(S\) 表示 \(a\) 的前缀和。把 \(S_r\) 提出来得到 \(S_r + \min(x - S_{l-1},\min_{i=l}^r(b_i - S_i))\)。注意到 \(l\) 右移时,前者变小,后者变大,可以在 sgt 上二分。时间复杂度 \(O(n + q\log n)\)。

10.16 C

维护 \(f_{i,x}\) 表示前 \(i\) 个数,\(x\) 的出现总次数。那么 \(j\) 能向 \(i\) 转移当且仅当 \(\forall x \in [1,m]\),\(f_{i,x} - f_{j,x}\) 相等。实质上就是差分数组相同。于是每个位置 \(f\) 的查分数组即可。时间复杂度 \(O(nm)\)。
更聪明的做法是,为 \(2 \sim m\) 随机一个哈希权值 \(V_i\),记 \(S = \sum V\)。令 \(1\) 的权值为 \(-S\)。那么一个区间合法当且仅当区间和为 \(0\)。容易维护。

10.16 D

不会做。搞笑。
经典套路是将 \(i \to 2i,2i+1\) 连边。子树内互不影响,树形 dp 即可。

P16522

经典根号分治。
\(y = kx + b\)。对于 \(|k| \in [0,200]\) 的情况,枚举 \(x\) 记录贡献。否则 \(|k| > 200\),有用的 \(x\) 至多 \(200\) 个,离线下来计算即可。时间复杂度 \(O(200n)\)。

P11659

容易想到莫队。用 \(c_{1,x}\) 表示区间 \((4x,2x)\) 数量,\(c_{2,x}\) 表示区间 \((2x,3x)\) 数量。
在维护区间的时候,如果加入左端点,若左端点 \(4\mid x\),只需加上 \(c_{2,x}\),同时更新 \(c_{1,x}\) 和 \(c_{2,x}\) 数量。
右端点也是同理。那么做完了。

10.17 B

记 \(X = \sum A_i\),\(Y = \sum B_i\)。显然答案 \(\ge \max(X,Y,\max(A_i+B_i))\),然后大胆猜测这个就是下界。容易 \(O(nq)\)。然后考虑怎么维护 \(\max(A_i+B_i)\)。显然当 \(A_i > \frac{X}{2}\) 或者 \(B_i > \frac{Y}{2}\) 时 \(i\) 才有贡献。维护区间 max 位置即可。

10.22 B

想对了一万步,那我说啥了。

注意到 \(c_i-a_i\) 极小,显然要把这个放进状态。记 \(w_i = c_i - a_i\),\(c_i = d_i-b_i\),那么有 \(w_i \le 10\)。
朴素的想法是 \(f_{i,j}\) 表示前 \(i\) 位,额外满意度为 \(j\) 的最小额外代价。可以二分出最后一个要交 \(e_i\) 的 \(k\),转移

\[f_{i,j} = \begin{cases} f_{p,j-w_i} + e_i + c_i,p \le k \\ f_{p,j-w_i} + c_i, p > k \end{cases} \]

由于 \(w_i \le 10\),我们只关心最近几个 \(f_{p,j},f_{p,j-1} \cdots f_{p,j-w_i}\),滚动数组即可。前者维护前缀最小值,后者使用单调队列维护一个窗口。

CF466E

菜完了呗。

很好的事情是一个文件至多只会在一个节点被标记。我们总是会在某个时间询问 \(A\) 是否是 \(B\) 的某个祖先,这等价于:

  • 这个时间 \(A,B\) 连通。
  • 最后的时刻,\(A\) 是 \(B\) 的祖先。。。这个东西是不会改变的。。。

第二项容易挂在节点上 dfs 一遍维护。那么做完了。

10.24 B

容易会掉 \(70\) 分。\(f_{i,j,k,l}\) 表示前 \(i\) 个,当前剩余容量为 \(j\),拉了 \(k\) 个 \(1\),\(l\) 个 \(2\) 出来的最小车辆数。这是因为对于固定的 \(k\) 个 \(1\),\(l\) 个 \(2\) 可以贪心预处理。那么时间复杂度 \(O(n^3w)\),实际可以过掉 \(90\)。
然后需要一个贪心,显然每辆车浪费的空间只可能是 \(1\) 或 \(2\)。那么 \(f_{i,k,l}\) 表示前 \(i\) 个,\(k\) 个 \(1\),\(l\) 个 \(2\) 的最小浪费空间。可以反推出用了几辆车,当前这辆的剩余空间。那么时间复杂度 \(O(n^3)\)。

P9220

真昼!

显然要缩点,然后容易发现如果先手无法一步必胜,后手无法两步必胜,那一定是平局。否则后手肯定可以消掉先手的贡献。

  • 先手必胜。缩点完找到 topo 深度最浅的节点,暴力做一遍。
  • 后手必胜。只有三种情况:初始全白。两个黑色孤立点。两个点,黑指向白。这些都是容易判断的。

时间复杂度 \(O(n + m)\)。

10.26 B

gp。
考虑怎么计算 \(f(n, m)\)。考虑按位贪心,两个 \(0\) 显然只能填 \(0\),一个 \(1\) 一个 \(0\) 也只能对应填,否则两个 \(1\),只填 \(1\) 个,后面的位就可以全填 \(1\) 了。
考虑差分完数位 dp。\(S(n,m)\) 表示 \(\sum_{i=0}^n \sum_{j=0}^m\) 的答案。快速计算 \(S(n,m)\)。
考虑计算每一位的贡献,\(f(p,f_1,f_2,f_3)\) 表示第 \(p\) 位,\(f_1,f_2\) 表示 \(n,m\) 的限制是否是紧的,\(f_3\) 表示是否存在一个位置是两个 \(1\)(这样后面可以任意填 \(1\))。
转移的时候,枚举两个数当前位填什么,先计算新的 \(f(p-1f_1',f_2',f_3')\) 的答案(方案数和贡献)。方案数直接加,贡献的话如果 \(f_3 \lor (i=1 \lor j = 1)\) 为真,则该位后面任意填,都有 \(1\) 的贡献。时间复杂度 \(O(256L)\)。

pii dfs(ll pos, bool f1, bool f2, bool f3) {
	if (pos < 0) return {1, 0}; 
	if (vis[pos][f1][f2][f3]) 
		return dp[pos][f1][f2][f3]; 
	vis[pos][f1][f2][f3] = true; 
	#define fnw dp[pos][f1][f2][f3] 
	fnw = {0, 0}; 
	ll lim1 = f1 ? a[pos] - '0' : 1; 
	ll lim2 = f2 ? b[pos] - '0' : 1; 
 	for (ll i = 0; i <= lim1; ++ i ) {
		for (ll j = 0; j <= lim2; ++ j ) {
			bool nt1 = f1 && (i == a[pos] - '0'); 
			bool nt2 = f2 && (j == b[pos] - '0'); 
			bool nt3 = f3 || (i == 1 && j == 1); 
			pii res = dfs(pos - 1, nt1, nt2, nt3); 
			fnw.fi = (fnw.fi + res.fi) % mod; 
			fnw.se = (fnw.se + res.se + res.fi * pw2[pos] % mod * (nt3 || i != j)) % mod; 
		}
	}
	#undef fnw 
	return dp[pos][f1][f2][f3]; 
}

P3203

典啊。
考虑分块,维护每个位置跳几次能出块,以及出块到的是哪里。
带修的话就对整块暴力修,然后最多跳 \(\sqrt n\) 次就能出去。时间复杂度 \(O(n\sqrt n)\)。

P14363

神题。有一万种做法可以过掉这个题。
考虑把 \(s_1,s_2\) 刻画成 \(x+y+z\) 和 \(x + y' + z\) 的形式。把 \(t_1,t_2\) 刻画成 \(a+b+c\) 和 \(a+b'+c\) 的形式。
那么一个匹配合法当且仅当 \(y=b,y'=b'\),\(x\) 为 \(a\) 后缀,\(z\) 为 \(c\) 的前缀。如果把 \((y,y')\) 映射就是 P9196。

P3514

可以扩展到区间询问。
找到第一个 \(s_r \ge x\) 的 \(r\),如果不对必定满足 \(s_r = x + 1 \land A_r = 2\)。
你考虑双指针初始 \(l=1\),指针移动的时候必定满足两端都是 \(2\)。维护 \(i\) 往右 \(2\) 的连续个数即可。

P9196

弱化。

先把后缀翻转后转成前缀,建出正反两个 trie。然后询问可以在两个 trie 上走到对应的两个节点 \(u,v\),就是要询问同时在 \(u,v\) 子树内的点的个数,拍到 dfn 序上二维数点即可。

P5391

gp!

很妙的转化是转化成一珂树,然后对每条链来做。\(O(nq)\) 是能过的,瓶颈在于空间。考虑用书剖优化,由于一条链上的重链个数是 \(O(\log n)\) 的,于是每条重链只开一个 dp 数组。当前在做 \(f_{dep,0\sim m}\),轻儿子就用 \(f_{dep+1,0\sim m}\),重儿子就用 \(f_{dep,0\sim m}\) 继续覆盖。空间复杂度 \(O(m\log n)\)。

P15958

先考虑把所有位置赋值为 \(-1\),然后对于每个限制,在 \(r\) 进行考虑,贪心的选择最靠近的几个点改成 \(1\),因为限制是 \(\ge\),不会影响之前的答案。使用 bit 维护即可。

10.28 C

gp。

考虑一个合法的答案位置 \(p\),优化是只保留 \(\le a_p\) 的 \(k-1\) 个值,正确性显然。你发现删完之后,因为后面的每个 \(i \ge p\) 满足 \(a_i \ge a_{i-1},a_{i-2},\cdots a_{i-k+1}\),是以斐波那契数列增长的,合法的 \(i\) 至多 \(100\) 个(还大了)。每次暴力扫,维护即可。时间复杂度 \(O(n\log n)\)。

P9002

结论是去掉最高位之后,至多一个 \(b-2\),剩下要求全是 \(b-1\)。分讨最高位计数即可。

P13547

bit 简单题。记 \(f(i)\) 表示 \(1 \sim i\) 相同的方案数(相同排列重复计数)。枚举不同的位置 \(i\),那么 \(1 \sim i-1\) 都确定了,如果当前还有 \(k\) 个数方案数就是 \(f(i-1)k(n-i)!\)。由于有相同元素,答案要除掉 \(\prod_x cnt_x!\)。注意如果 \(s\) 是 \(t\) 前缀,长度更短字典序也更小,还要加上 \(f(n)\) 再除。

10.29 C

很好的计数。我不会。

考虑找村民的子序列,枚举狼有 \(t\) 个,村民有 \(m = n - t\) 个。
那么对于某个位置,如果它要成为村民,可以计算出 \(c_i\) 表示它左边要放多少个村民。如果 \(c_i \notin [0,m]\),\(i\) 一定要是狼。
那么选出来的 \(c\) 值序列一定是 \(0,1,2,\cdots m-1\)。容易 dp 计数。时间复杂度 \(O(n^2)\),正解要上 sgt 矩阵优化。

P11761

套路地,中位数转成 \(-1/1\) 序列。考虑二分答案,如果中位数要是 \(-1\),当且仅当序列和 \(\le 0\)!转成 \(01\) 序列后,\(f_{i,j}\) 表示前 \(i\) 位,每一段中位数和为 \(j\) 的方案数。

P17747

容易会掉线性。\(f(n) = S(n - 1) - S(\sqrt n) = 2f(n-1) - f(\sqrt n)\)。
考虑当 \(k = \sqrt n\) 为定值时,\(f(n) - f(k) = 2(f(n-1) - f(k))\),也就是 \(f(n) - f(k)\) 一直在翻倍!于是对于每一个完全平方数的段可以快速计算。时间复杂度应该是 \(O(\sqrt n)\)。

P7322

\(f\) 由若干连续段形成。只需统计 \(f_i \ne f_{i-1}\) 的贡献。
考虑 \(f_i,f_{i+1}\),是相邻两个长度为 \(k\) 的区间的 \(\max\)。\(f_i \ne f_{i+1}\) 当且仅当最大值位于区间头或尾。一共 \(n!\) 个排列,存在某个长度为 \(k+1\) 的区间满足最大值位于头,尾的概率就是 \((n-k)\frac{2}{k+1}\)。答案即 \(n!(n-k)\frac{2}{k+1}\)。最后每个排列都少算了一次,因为我们漏了开头的 \(f_1\)。再加上 \(n!\) 即可。

10.31 B

由于只关心最后的答案,很好的转化是枚举 \(t\),然后判断哪个区间 \(\ge t\) 的点更多。因为一个显然的结论是 \(t\) 肯定是某个 \(a\)。考虑按 \(a\) 大到小排序插入,考虑每个区间的贡献。对于一个固定的左端点 \(l\),你把它的右端点换成 \(\le l\) 的区间的 \(r\) 的最大值显然不会影响答案。做完这件事后,按区间左端点 \(l\) 排序,\(r\) 也单调了。在插入一个位置在 \(p\) 的 \(t\) 时,覆盖它的区间编号显然是一段前缀、后缀,并起来区间加即可。使用 sgt 维护时间复杂度 \(O(m\log m)\)。

AT_dp_t

gp,比较典。

考虑任意一个合法状态我们需要什么,需要已经插入的数的个数以及最后一个数的排名。于是 \(f_{i,j}\) 表示插入前 \(i\) 个数,最后一个数的排名为 \(j\)。容易做到 \(O(n^3)\),前缀和随便优化 \(O(n^2)\)。

10.30 C

巧妙的转化是放在树上,压入就新建一个节点然后挂在原来的栈顶,弹出就把 \(p,q\) 向 \((p+q)\bmod n\) 连边。在新树上树形 dp。
还是不太懂。

AT_dp_j

gp。

我们只关心 \(1,2,3\) 的数量。dp \(f_{a,b,c}\) 表示 \(a\) 个 \(1\),\(b\) 个 \(2\),\(c\) 个 \(3\)。由于等概率容易转移。

AT_dp_o

容易想到状压。时间复杂度 \(O(n^22^n)\),可以通过。

bool nums[50][50];

ll f[50][1 << 22];

const ll mod = 1e9 + 7;

int main()
{
	int n;
	cin >> n;	
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			cin >> nums[i][j];
	f[0][0] = 1;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < (1 << n); j++)
			if (__builtin_popcount(j) == i)
				for (int k = 0; k < n; k++)
					if (nums[i][k] && (j & (1 << k)) == 0)
						f[i + 1][j | (1 << k)] = 
						(f[i + 1][j | (1 << k)] + f[i][j]) % mod;
	cout << f[n][(1 << n) - 1];
	return 0;
}

常见优化是把 \(i\) 扔掉,直接按 \([0,2^n-1]\) 扫,容易证明扫到某个状态时,它的所有前驱都算完了。时间复杂度 \(O(2^nn)\)。轻松通过。

AT_dp_u

状压 dp。转移的时候枚举子集扣掉,因为枚举子集是 \(O(3^n)\) 的,预处理 \(O(2^nn^2)\)。

for (ll p = ms; p > 0; p = (p - 1) & ms) ...

11.3 A

考虑 dp。\(f_i\) 表示强制 \(i\) 要选最小的个数。\(i\) 要从 \(j\) 转移过来?

  • \(j = i- 1\),合法。
  • \(A_{j+1}-A_j \ge L\),\(A_{i+1}-A_i \ge L\),不存在 \(k\) 使得 \(\max(A_i - A_k, A_k - A_j) > R\)。

对每个 \(j\) 维护 \(nxt_j=i\) 表示最大的合法位置使得:不存在 \(k\) 使得 \(\max(A_i - A_k, A_k - A_j) > R\)。
注意到 \(nxt\) 具有单调性,对于某个 \(i\),合法的 \(j\) 肯定是一段合法区间。在线段树上维护区间 \(f\) 最小值即可。注意如果 \(A_{i+1}-A_i < L\),线段树上位置 \(i\) 不能用 \(f_i\) 更新。

11.3 B

做不明白这种题啊。。。
考虑刻画最终的答案。可以证明答案肯定是 \(\sum_{i=1}^n s_iA_i + dK\),其中 \(s_i = {-1,1}\),等价于给每个 \(A_i\) 标一个 \(-1/1\)。假设其中有 \(m\) 的负数,肯定要排序后取前 \(m\) 小放 \(-1\)。你考虑 \(d\) 怎么算,打表出来 \(d = \frac{2m - (n-1)}{3}\)。那么 \(m \equiv 1 - N \pmod{3}\),\(m\) 只会有 \(O(n)\) 种取值,记 \(f(K,m) = d(m)K + S - 2p_m\),其中 \(p\) 是小到大排序的前缀和。打表再次发现 \(f(K,m)\) 关于 \(m\) 单峰,使用二分即可。

P5851

区间 dp,考虑怎么转移。
\(f_{l,r} = f_{l,k-1} + f_{k+1,r} + g(k,l,r)\),这是在强制 \(k\) 被当前这个奶牛吃掉,加入这个奶牛的贡献。\(g(k,l,r)\) 表示满足 \(l \le l_p \le k \le r_p\le r\) 的 \(w_p\) 最大值。可以预处理。时间复杂度 \(O(n^3)\)。

AT_dp_v

维护 \(dp_1\) 表示 \(u\) 子树内,染成黑色的节点与 \(u\) 在同个连通块的方案数。\(dp_2\) 表示 \(u\) 子树外的。转移的时候

\[dp_{1,u} = \prod_{v \in son(u)} (dp_{1,v} + 1)\\ dp_{2,u} = 1 + dp_{2,fa} \times (\prod_{v \in brother(u)}dp_{1,v} + 1) \]

后者的 \(1\) 表示外部什么都不选。由于 \(m\) 不一定是质数,不能直接除以 \(u\) 的贡献,维护前缀后缀积即可。时间复杂度线性。

P10375

考虑任意一个状态,我们关心什么,合法的串一定形如 a..ab...bc...c。
考虑当前一个不合法的串 a...ab...bc...cde...,在末尾加入 \(a,b,c,d\) 显然是合法的,\(e\) 不行是因为它前面的串不合法。于是我们记 \(j\) 表示当前状态里,合法的元素个数(即 \(a,b,c,d\)),把它放进状态。\(f_{i,j,k}\) 表示放了 \(i\) 个,有 \(j\) 个合法,\(k=0/1\) 表示当前串是否合法的方案数。加入一个合法 / 不合法的元素转移即可。时间复杂度 \(O(n^2)\)。

P6009

序列区间询问,容易想到猫树,但是怎么合并?
从中点 \(mid\) 开始往前扫,维护 \(L_{j,k}\) 表示当前后缀里以 \(j\) 开头 \(k\) 结尾的方案数,得到 \(pre_{i,k}\) 表示后缀 \(i\) 里 \(k\) 结尾的方案数。
同理得到 \(suf_{i,k}\) 表示前缀 \(i\) 以 \(k\) 结尾的方案数。对于询问 \(L,R\),枚举 \(i,j\),方案数 \(pre_{L,i} + suf_{R,j} + pre_{L,i} \times suf_{R,j}\) 注意最后的要求 \(i \le j\)。时间复杂度 \(O((n\log n + q)k^2)\)。

P9327

做不明白。
把边按 \(l\) 排序。遍历到某条边,如果当前两点的最短距离 \(<l\),显然这条边没用。否则这条边肯定要加上,因为后面的边不会改变这两点的最短距离。求当前的最短距离跑 dj 即可。时间复杂度 \(O(m^2\log m)\)。

P10960

显然除了 \(a_1,a_2\),每个数都可以标上一个符号。考虑 dp 求解每个数前标的符号,然后考虑怎么构造。
对于那些标加号的数,用它前面的一个先减一下。最后用 \(a_1\) 一直减即可。

P3694

\(m\) 很小考虑状压。由于确定了某个状态,假设这个状态共 \(k\) 个人,那么 \([1,k]\) 都被确定了,把里面不属于这个状态的人踢掉即可。容易转移。

P7872

gp。多线程 dp。
预处理出 \(g_{i,j}\) 表示第二个人从 \((i,j)\) 走到终点,不考虑第一个人的贡献,随便预处理。
考察两人的移动过程,第一个人一定在相遇时把正数扔给第二个人,负数随便找个地方可以扔掉。\(f_{i,j,k}\) 表示两人走了 \(i\) 步,第一个人走 \(j\) 步,第二个 \(k\) 步。\(f_{i,j,k}\) 假设了两人后面一定可以相遇一次,那么每次在状态改变时和 \(g\) 记录答案即可(如相遇变分离,分离变相遇)。注意还要特判第一个人能走到第二个人的终点。

P9759

不是大哥,这个 trick 之前不是见过吗 /ll
容易会掉 \(O(n^2k)\)。然后第三维可以放和 \(k\) 的 gcd。于是做完了。但是你枚举从 \(o\) 转移到 \(\gcd(o \times v,k)\),要带个 log,使用 \(O(1)\) gcd 也无法通过。考虑预处理一下,显然可以先对 \(v\) 和 \(k\) 取 gcd,这样有用的数只有 \(d(k)\) 种,平方预处理出因子两两之积和 \(k\) 的 gcd 即可做到 \(O(1)\) 转移。

P6234

不会这种题。哎,啥子吧。

你考虑对于每个关键点,是不是可以看成四联通然后拿掉一个。你考虑重叠的关键点,每个连通块显然可以分开做。对于每个连通块,记关键点数量为 \(x\),总点数为 \(y\) 分讨:

  • \(4x=y\),这是好事啊,全都能取。
  • \(4x > y\),无解。
  • \(4x < y\) 有空位,手玩发现至多 \(1\) 个,也就是 \(4x + 1 = y\)。这是因为总共 \(5x\) 个点,要重叠至少浪费一个格,总共 \(x-1\) 个格子,也就是至多 \(5x - (x-1) = 4x+1\) 个格子。那么扔掉最小的那个即可。

11.9 C

gp。

显然要对于固定的串,刻画合法的充要条件。
记 \(\Delta\) 表示 \(1\) 的个数减去 \(0\) 的个数。当 \(\delta > 0\) 时合法。简单的贪心是,把 \(000\) 优先并掉,以及 \(010\) 并掉(可能有 \(000\) 可以再次合并)。第一个使得 \(\Delta \to \Delta + 2\),第二个 \(\Delta\) 不变。只需判断最后 \(\Delta\) 是否 \(> 0\)。
然后考虑 dp 维护当前的后缀,容易发现只会有 \(\{0,00,01,001,\emptyset\}\) 五种情况,把这个放进状态容易转移,然后还要关心 \(\Delta\) 的值,手玩发现有用的 \(\Delta \in [-2,3]\),上界是因为到了 \(3\) 一定合法,下界是因为只能到 \(-2\)。
那么 \(f_{i,j,k}\) 表示前 \(i\) 位,\(\Delta = j\),当前的后缀情况为 \(k\) 的方案数。容易转移。

P3554

显然可以二分,显然的结论是 B 不会走回头路。
记 \(f_i\) 表示 \(i\) 子树内需要染色的个数,\(son_i\) 表示 \(i\) 的儿子数量。\(f_i = \max(0,\sum f_j + son_i - k)\)。最后只需判断 \(f_1 = 0\)。

P6902

断环成链。考察固定起点的情况,经典的贪心是每次找到左端点 $\le $ 覆盖区间右端点加一的区间,的右端点的最大值跳过去,直到与起点的距离 \(\ge n\)。枚举起点每次跳肯定不现实,注意到这个是固定的过程,可以预处理然后倍增优化。

P14835

arc 水平,哎。感觉做不明白这种 arc 题。

考虑把前导 \(0\) 扔掉,不影响答案。
打表可以发现规律,\(x\) 一定由一段前缀所有的 \(1\) 组成,剩下的放进 \(y\)。感性理解一下,如果 \(x\) 掺杂 \(0\),扔到 \(y\) 那里去不会使得答案更劣。
然后很容易想到 \(x\) 和 \(y\)(去除前导 \(0\) 后)的位数尽量接近时更优。那么容易维护了。

P17820

gp。

考虑每个局面对答案影响的期望,加起来就是答案。更具体的,假设当前 \(k\) 种颜色的球里,所有球剩余个数最多的为 \(m\),还剩下 \(s\) 个球。记 \(cnt_{m,s}\) 表示能到这个局面的方案数。这个局面的期望就是 \(\frac{m}{s}\times \frac{cnt_{m,s}}。{\binom{nk}{s}}\),枚举 \(m,s\) 求和即为答案。
来考虑怎么求 \(cnt_{m,s}\)。至多为 \(m\) 很恶心,转为恰好为 \(m\) 然后差分。\(f_{m,q,s}\) 表示,出现次数最多的个数 \(\le m\)(可能没到上界),考虑 \(q\) 种颜色,剩下 \(s\) 个球,那么 \(cnt_{m,s} = f_{m,k,s} - f_{m-1,k,s}\)。考虑 \(f\) 咋转移,每次枚举有 \(j\) 个球标了 \(m\) 个,\(f_{i,j,s+jm} \leftarrow f_{i-1,j-l,s} \times \binom{j}{l} \times \binom{n}{m}^j\)。时间复杂度 \(O(n^2k^3)\),滚动一下数组卡常即可通过。

P3118

简单状压。\(f_i\) 表示状态为 \(i\),能覆盖 \([0,f_i]\)。

P15543

不会做,急眼了。

考虑 \(k=0\) 的情况,对于每个 \(i\),假设右边有 \(j\) 个数满足 \(a_j < a_i\),那么要求栈容量至少为 \(j\),这个比较显然,答案就是每个 \(i\) 对应 \(j\) 的最大值。显然可以 bit 维护。
你考虑如果能加怎么办,显然可以二分答案。预处理出每个 \(i\) 对应的 \(j\),不妨记为 \(c_i\)。你可以得到每个非零数右边需要抬升到它的零的个数。打个标记,最后倒序遍历每个零,计算需要这个零抬升到哪,加起来判断是否 \(\le k\) 即可。时间复杂度 \(O(n\log n)\)。

P14508

gp。
记 \(V = \max a\)。显然我们只关心答案点所在的区间长度。记 \(f_i\) 表示答案点在长度为 \(i\) 的区间,最坏情况下的代价,对决策进行 dp。枚举上一步走的决策 \(l \in [1,\min(i-1,V)]\),就有 \(\max(f_l, f_{i-l}) + d_l\) 来更新答案(因为是最坏情况),\(d_l\) 表示走 \(l\) 步的最小代价。
考虑怎么计算 \(d_l\),你发现这个东西可以迪杰,考虑 \(l\) 的上界是多少。实际上,有效的点只有 \(O(2V)\) 个,因为如果存在一种移动要一直往右走再往左走,你调整成一步右一步左,\(>V\) 的时候往左,\(<V\) 的时候往右。上界即为 \(2V\)。时间复杂度 \(O(T(nV + V^2))\)。

P12846

好烫,但是我不会,可能我更烫。
考虑对 \(6\) 取模来对下标做分类。维护六珂线段树即可。代码比较恶心,口胡了没写。

P10767

之前做过类似的题,感觉很那啥。
维护每个节点,如果要到这个节点至少需要多少个数小于它,多少个数大于它,不妨记为 \(l_u,r_u\)。
考虑如果是 max 的话,有 \(l_u = l_{ls}+l_{rs}+1\),\(r_u = \min(r_{ls},r_{rs})\)。
min 同理。

P6617

考虑对于每个位置 \(i\),维护 \(j < i\) 满足 \(a_j+a_i=w\) 的 \(\max j\),也就是前驱。查询的时候在线段树上查最值即可。
然后考虑带修怎么办,首先一个巧妙的转化是,对于某个位置的数,如果它的前驱比与它相同的上一个元素还靠前,把这个位置的前驱赋成 \(0\) 不会影响答案。这样修改的时候,只会修改这个位置,这个位置原来后面第一个与他相同的位置,这个位置原来后面第一个与他相加得 \(w\) 的位置,这个位置后来后面第一个与他相同的位置,这个位置后来后面第一个与他相加得 \(w\) 的位置。使用 set 维护即可,时间复杂度 \(O(n\log n)\),代码没写。

P8564

简单树形 dp。\(f_{i,j}\) 表示 \(i\) 子树内删了 \(j\),转移枚举几个儿子分配了即可。再考虑 \(i\) 操不操作即可。时间复杂度 \(O(n^2)\)。

P9346

题目等价于,把一棵树变成若干条链。来考虑期望的定义,总花费除以总方案数。总方案数显然是 \((n-1)!\)。考虑怎么算总花费,考虑 \(f_i\) 表示断掉 \(i\) 条边之后,第一次凋零的方案数。但是这个好难算,熔池一下 \(g_i\) 表示断掉 \(i\) 条边,不要求第一次凋零的方案数,有 \(f_i = i!(n-i-1)!g_i - \sum_{j=1}^{i-1}{f_j}\)。
现在要计算 \(g_i\),树形 dp 一下,\(f_{i,j,k}\) 表示 \(i\) 子树内,断了 \(j\) 条边,\(i\) 的度数为 \(k \in \{0,1,2\}\)。转移考虑这条边断不断。最后 \(g_i = \sum_k f_{1,i,k}\)。

P17140

难度:蓝

咕了很久的 dp。
考虑啥时候会是树,你发现一个点至多被覆盖两次,然后要求覆盖的点连通。把线段按左端点排序,现在考虑第 \(i\) 条线段。两次我们关心右端点的次大值,连通关心最大值,把这两个东西放到状态里。\(f_{i,r_1,r_2,k}\) 表示考虑前 \(i\) 条线段,当前选的线段右端点的最大 / 次大值为 \(r_1,r_2\),选了 \(k\) 条的方案数。转移的时候:

  • 不选 \(i\),\(f_{i,r_1,r_2,k} \leftarrow f_{i-1,r_1,r_2,k}\)。
  • 选 \(i\),那么 \(l_i > r_2\)。你分讨右端点在哪,如果 \(r_2 < l_i \le r_i \le r_1\),有 \(f_{i,r_1,r_i,k} \leftarrow f_{i-1,r_1,r_2,k-1}\)。如果 \(r_2 < l_i \le r_1 < r_i\),有 \(f_{i,r_i,r_1,k} \leftarrow f_{i-1,r_1,r_2,k-1}\)。

那么滚动掉 \(i\) 就会 \(O(nm^2k)\) 了,获得滚木分数。
注意到 \(k\) 也只关心 \(k-1\),考虑提出来把 \(k\) 看作层,对每个 \(k\) 进行 dp。重新写一下转移:

  • \(f_{i,r_1,r_2} \leftarrow f_{i-1,r_1,r_2}\)。
  • \(f_{i,r_1,r_i} \leftarrow g_{i-1,r_1,r_2}\)。
  • \(f_{i,r_i,r_1} \leftarrow g_{i-1,r_1,r_2}\)。
posted @ 2026-09-14 09:49  RainyRadio  阅读(11)  评论(0)    收藏  举报