🍕🏠🌋 当前时间是:

 

设蚂蚁

[PA 2019] Desant

让求取到最小值的方案数,看上去就不太可做。再结合数据范围,考虑 exp 做法。

一个暴力是:按值域从小往大填数,一个数的贡献就是它在填进序列时在它后面已经填好的数。

状压每个位置有没有填数可以得到简单的 \(O(2^n\text{poly}(n))\) 的做法。

考虑能不能合并一些对逆序对的贡献本质相同的状态。

经过观察可以发现,假设现在考虑完了前 \(t\) 大的数,那么相邻两个 \(\leq t\) 的数只选第一个和只选第二个是没有区别的。

扩展一下就是:对于一个极长的只包含 \(\leq t\) 的数的区间,我们只关心这个区间内选了多少个数。

来估算一下状态量:

先假设能给这个 \(t\) 个数任意分段,根据经典结论,每段长最好为 2,也就是状态的数量级是 \(O(3^{\frac{t}{2}})\),而这要求 \(t<\dfrac{2n}{3}\)

如果 \(t\ge \dfrac{2n}{3}\),那么尽可能均分状态量是最大的,数量级是 \((\dfrac{t}{n-t+1}+1)^{n-t+1}\),这大概是 \(\sum\limits_{1\leq x\leq \frac{n}{3}} (\dfrac{n}{x})^x\),也就是 \(\sum\limits_{3\leq x\leq n} x^{\frac{n}{x}}\),在 \(3\) 处取到最值,后面指数级减小。

所以我们说明了状态量是 \(O(3^{\frac{n}{3}}n)\) 的。

最后 dp 的复杂度是 \(O(3^{\frac{n}{3}}n^2)\),手写哈希表可以通过。

代码

[PA 2021] Desant 2

由于 \(k\) 是常数,以 \(k\) 为块长对序列分块,建立一个 \(k\times \lceil\dfrac{n}{k}\rceil\) 的网格图,图上 \((i,j)\) 格子代表序列中 \((i-1)\times k+j\) 位置的士兵。

那么 dp 的过程相当于:网格图上每个格子 \((i,j)\) 能花费 0 的代价向右走(每一行最右边的格子走到下一行开头),或者花费 \(s_{(i+1,j-1)}-s_{(i,j-1)}\) 的代价向下走一格(\(s_{(i,j)}\) 表示格子 \((i,j)\) 在序列中的前缀和),要求从一个点 dp 到另一个点的最大代价。

网格图上路径统计问题容易想到分治,每次从横竖两个方向较大的一维选出一条中线,然后枚举中线上的每个点,求它到两侧每个点的最大代价,然后对于一组询问,统计在这个点的贡献。需要注意,这个点应在询问两点在序列中位置的中间。

手玩一下可以发现,递归处理一个子矩形时,要把起点终点都被这个子矩形包含的询问都处理。

还有一种 case ,画竖线分治时可能在线异侧的一组询问最长路不经过这条线上的点,但它一定会经过当前子矩形最右边一列,所以再对这一列统计一遍答案。但这种 case 只需要在第一次划竖线时考虑,所以不会显著增加常数。

分治的复杂度是 \(f(n)=O(n\sqrt{n})+2f(n/2)=O(n\sqrt{n})\) 的。

代码

[PA 2024] Desant 3

似乎一眼很难想到有什么 poly 或者比较快的 exp 做法。

这个对 2 取模非常神秘,考虑找双射把一些 case 抵消掉。

考虑第一个操作,如果这两个位置的值是 10,那么经过这次操作,这两个位置的值和 01 是没有区别的。所以如果第一个操作的两个位置的值不相等,它们对答案的贡献是 0。

由此可以想到依次考虑每个操作,维护每个位置的状态,分别是“不确定(x)”、“0”、“1”。

如果考虑到的操作的两个位置都不确定,那么要求这两个位置数值相等,枚举是什么,状态会产生两个。

如果考虑到的操作的两个位置都确定,直接模拟 swap,状态量不变。

现在要考虑只有一个位置确定该怎么办:经过观察可以发现,如果形如 “x0”,那么可以变成 “0x”;如果形如 “1x”,可以变成 “x1”。以此类推,状态量不变。

最后对所有最终状态统计答案即可。

可以发现,只有两个位置都不确定的时候才会状态量翻倍,这件事最多发生 \(\lfloor\dfrac{n}{2}\rfloor\) 次,所以每一轮状态量最多是 \(O(2^{\frac{n}{2}})\) 的。

最后复杂度就是 \(O(2^{\frac{n}{2}}(m+n^3))\),(\(n^3\) 是统计答案,当然这部分也可以做到更低)。

代码

posted @ 2025-06-26 18:52  zzafanti  阅读(24)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end