思维题收集

我需要练思维!

所以我参考了一些题单。

挑战这些题做完之后能做到不使用任何 AI 工具、不看任何一篇题解。

1. 题单:思维 - Level 1

青蓝紫黑做不动,先做点绿吧。

这一部分全都是 USACO 的题,25 年 CSP 前夕@鲤鱼江学长建议我多做这些题。但现在已经是什么时候了啊。我居然是在他 AFO 之后才开始践行这个的。

呃有可能不是按题单顺序做的,大概就是自己挑了一些来做。

P6005

做该题使用了 AI 工具。

一开始觉得是最长路。然后还在想拆点,后来实在忍不住了。

不过比较好的是想到了看跑几轮最大的。

考虑 dp。设 \(dp_{u,k}\) 表示当前在点 \(u\),现在已经过去了 \(k\) 天。显然有 \(dp_{u,k}=\max_{v 可以到达 u}\{dp_{v,k-1}\}\)。初始时 \(dp_{1,0}=0\),其他的是 \(-\inf\),最终答案是 \(\max_{1\le k\le1000}\{dp_{1,k}\}\)

为什么是 \(1\le k\le1000\) 呢?考虑每个点都是 \(1000\) 的贡献,你跑 \(1000\) 次可以获得 \(10^6\) 的贡献,但是此时你需要付出的代价已经来到了 \(1000^2=10^6\) 级别,再继续跑收益就为负了。

P8186

做该题使用了 AI 工具。

最初没有思路,偷看了一眼算法标签看见了二分图,于是想到二分图匹配。但是这个做法是假的,因为这不是问你能不能合理分配,而是每个最优情况下可能分配到的。

然后问了 deepseek,发现是一个 Floyd 传递闭包。值得庆幸的是建图方式是对的,至少并没有全错。

显然贪心的考虑,对于当前的 \(i\),它向它的愿望之前的礼物连一条有向边,表示可能会选到这个礼物。然后跑传递闭包,最后看哪一个礼物能连回来。

P6149

做该题用了 AI 也看了题解。

一开始还看错题了。写了一个感觉很对的做法但是不知道哪里写挂了。

好,通过 deepseek 的大力调试成功发现我的做法确实是对的,只是式子推到一半因为条件写错了导致遗憾离场。

发现暴力枚举三个顶点显然直接起飞,又发现这个三角形是直角三角形,所以考虑枚举直角顶点 \(A\),计算下列式子的值:

\[\begin{aligned} &\sum_{B\mid x_B=x_A}\sum_{C\mid y_C=y_A}|x_B-x_A||y_C-y_A|\\ =&\sum_{B\mid y_B=y_A}|x_B-x_A|\sum_{C\mid x_C=x_A}|y_C-y_A| \end{aligned} \]

先只看 \(\sum_{B\mid y_B=y_A}|x_B-x_A|\)(因为后面那个处理方法是一样的)。发现绝对值很烦,又发现实际上可以按照 \(x_B<x_A\)\(x_B\ge x_A\) 进行分类。设 \(A\) 点在与其纵坐标相同的点中排第 \(i\) 个(默认从小到大),与其纵坐标相同的点共 \(k\) 个,所以对于同一个纵坐标:

\[\begin{aligned} &\sum_{B\mid y_B=y_A}|x_B-x_A|\\ =&\sum_{B\mid y_B=y_A\And x_B<x_A}x_A-x_B+\sum_{B\mid y_B=y_A\And x_B\ge x_A}x_B-x_A\\ =&(i-1)x_A-\sum_{B\mid y_B=y_A\And x_B<x_A}x_B-(k-i)x_A+\sum_{B\mid y_B=y_A\And x_B\ge x_A}x_B\\ =&(2i-k-1)x_A-\sum_{B\mid y_B=y_A\And x_B<x_A}x_B+\sum_{B\mid y_B=y_A\And x_B\ge x_A}x_B \end{aligned} \]

然后你对 \(x_B\) 求一个前缀和就可以 \(O(1)\) 算出 \(A\) 点这里的答案。对于 \(\sum_{C\mid y_C=y_A}|y_C-y_A|\) 的处理是一样的,最后对于每一个点把横纵坐标的贡献乘起来并求和即可。

P7149

AI 太【请文明用语】了,所以看题解。

首先肯定要排序。

其次肯定要离散化。

然后你发现,对于不同的矩形,如果框住的牛的集合是完全相同的,那么这些矩形也是相同的。所以贪心的考虑,我们把牛放在边界上,就能处理所有等价情况。

由于是一个二维平面上,所以维护二维前缀和来算出任意矩形区域的牛的数量。然后将所有点按照 \(y\) 进行排序,枚举矩形的上下边界参考点 \(i\)\(j\),然后独立选择左右边界截断位置,通过乘法原理统计所有可能的内部点集。

P7150

使用了 AI。

应该算好题吧。思维转化是有的。

首先你容易发现每头牛走的是直线,然后你随便手玩一下样例又能发现,如果两头牛能够产生阻碍关系,那么两头牛一定一头向东,一头向北,且一定有 \(ex<nx\)\(ey>ny\),最后在交叉点 \((nx,ey)\) 发生阻碍。其中 \((ex,ey)\) 是向东走的牛的出发点,\((nx,ny)\) 同理。

考虑将每一个阻碍关系看作一个“事件”,表示在这个关系中哪头牛阻碍了哪头牛(分别记为 \(a\)\(b\)),什么时候注定之后会阻碍(也就是离交叉点近的牛到交叉点需要用的时间),什么时候发生了阻碍(也就是离交叉点远的牛到交叉点需要用的时间)。然后按照注定之后会阻碍的时间进行排序来处理每头牛的直接阻碍者。

具体的,如果 \(a\) 阻碍了 \(b\),就看一下 \(a\) 在到交叉点前是否被阻碍,以及 \(b\) 在到达交叉点前是否被阻碍,如果都没有被阻碍,说明 \(b\)\(a\) 直接阻挡,记录下来。

然后你又发现每头牛有且仅有一个直接阻碍者,这使得整个直接阻碍关系形成了森林,森林中的每棵树中祖先节点永远阻挡子孙节点。那么最终答案直接就出来了,就是每个节点的子树大小(不包含自己)。所以你去森林中每棵树的根节点开始遍历算就行了。

妙啊。

P8266

使用了 AI 也看了题解。

注意到反转任意一段前缀实际上是将奇数位置的和偶数位置的字符交换。于是考虑最简单的情况:反转长度为 \(2\) 的前缀,那么就相当于把里面的字符交换位置。所以我们把整个串看成若干长度为 \(2\) 的段组成的串,那么有以下四种情况:

  • HH:反不反转无所谓,因为对答案没有贡献。
  • GG:同上。
  • HG:我们不需要反转这个段。
  • GH:我们需要反转这个段。

所以我们就看这样的段,如果遇到的是 HG,我们就把它看成 \(0\),如果是 GH 就看成 \(1\),剩下的不用管。

于是问题就变成了:有一个 0/1 序列,求里面有多少相邻的位置上的数不同。特别的,如果这个 0/1 序列末尾是 \(1\)(也就是要反转),答案就要加 \(1\)

P7299

使用了 AI 也看了题解。

首先对整个序列进行题目中的 \(k\) 次操作,那么最终每一头牛都会对应的挪到另一个位置。假设第一轮 \(k\) 次操作中牛 \(A\)\(x\) 走到了 \(y\),牛 \(B\)\(z\) 走到了 \(x\),那么 \(B\) 在下一轮也会走到 \(y\)

以此类推,\(B\) 之后的牛也会走到 \(B\) 走到过的点,也就是 \(A\) 走过的点。容易发现这些牛形成了一个循环。

所以我们直接找到每头牛在 \(k\) 次操作后到达过的位置集合,然后用并查集维护这个循环,那么答案就是这头牛所处的循环的大小。

P7301

使用了 AI。做完后看了题解确认做法。

考虑以下一种情况(C 是填进去的牛,* 是不知道填了什么):

**CC**
******
******

对于这已经有牛的两列,怎么填才是合法的呢?显然是

**CC**
**..**
**CC**

考虑向两边扩展(假设向右),那么合法的方案有

**CCC*   **CC.*
**...*   **..C*
**CCC*   **CC.*

于是可以发现,对于这几列,牛是交替放置的。推广到行是一样的。也就是说,合法的放置方案中,要么行交替,要么列交替。

所以我们直接对每行每列进行计算,然后取最大即可。

P7410

使用了 AI。

发现直接求恰好并不容易,所以考虑容斥,用 \(\ge100\) 的贡献减去 \(\ge101\) 的贡献。

假设我们现在对 \(\ge100\) 的部分哈气。对于这个矩形,如果 \(a_{i,j}\ge100\),我们就把这个位置看作 \(1\),否则看作 \(0\)。那么问题就转化成了求有多少个子矩形里面只包含 \(1\)

容易发现从每一行忽略其下,往上看,每一列连续的 \(1\) 构成了类似直方图的东西,那么这就产生了高度不一的“柱子”。不妨枚举这个最矮的柱子是哪个,然后统计以这个高度为最矮的,能贡献多少。这个可以单调栈维护。设当前枚举到 \(cur\),用单调栈找到右边高度第一个小于 \(cur\) 的位置 \(R\),则 \(cur\)\(R-1\) 这段区间的柱子的高度都大于等于 \(h_{cur}\),再设 \(L\) 表示 \(cur\) 左边第一个比 \(cur\) 矮的,那么这段贡献就是 \(h_{cur}\times(cur-L)\times(R-cur)\)。对于 \(\ge101\) 的部分是一样的。

总复杂度 \(O(n^2)\)

P6004

自己想到了做法,使用 AI 确认了正确性。

可能算比较模板。

首先看见最大化最小,容易想到二分答案。那么设二分出来的答案为 \(x\),由于边权小于 \(x\) 的边会产生更小的答案,不符合设定,所以我们只连上边权大于等于 \(x\) 的边。

可以发现一个事实:如果存在一个连通块 \(\{p_1,p_2,\dots,p_k\}\),里面的点有权值 \(1,2,\dots,k\),则我们可以通过不断地交换直接相连的点的权值,使得最终满足 \(p_i=i\)。手玩一下可以得出是对的,证明似乎也不是很难。

证明 由于是连通块,不妨考虑它的一棵生成树。考虑叶子节点 $p_x$ 到权值为 $x$ 的点的一条简单路径,我们可以通过不断把 $x$ 经过这个路径换到 $p_x$ 上。此时因为已经满足 $p_x=x$,我们之后无需再操作这个点,所以我们直接将这个点删除。然后继续从叶子节点开始,不停删点,最后一定能把点删完。此时每个点都满足 $p_i=i$。

推广到 \(p_i=v\) 的情况也是同理。

所以我们直接用并查集维护边权大于等于 \(x\) 的边所连点的连通块,判断 \(p_i\) 是否和 \(i\) 在同一连通块内即可。

对于 \(-1\) 的情况……似乎只有初始时 \(p_i=i\) 才会出现吧……

posted @ 2026-07-08 20:46  XXh_Laoxu  阅读(10)  评论(0)    收藏  举报

转载请注明出处!


#页面摧毁游戏#
使用【上下左右】控制飞行器的运动
使用【空格】发射导弹
点击开始摧毁