CF div2 994 (A~E)

VP赛时三题,自我感觉发挥不错,唯一不满意的地方在于D题完全没有思路。

A

答案最多为2,因为最坏情况即为先将整个区间合并为一个数,若这个数不是0,则再将这个数变为0。

所以3种情况分类讨论即可:

  1. 全是0,则不需要操作 -> 0
  2. 只有一段非0连续区间 -> 1
  3. 不止1个非0连续区间 -> 2

code

B

首先,若只出现了一种字符,则一定可行,因为若只出现p,则可令序列为[1,2,...,n];若只出现s则可令序列为[n,n1,...,1]

否则,两种字符一定都有。考虑任意一对p,s
设形成的前缀(p)1k1的排列,后缀(s)1k2的排列
易得前缀和后缀必然相互包含
所以检查是否有一对不相互包含的前后缀即可,实现不再赘述。

code

C

构造题

此题赛时的做法分讨得比较麻烦,但好在保证了正确性,还是官方题解的做法比较简洁。但感觉此题复盘的意义不大,故不再赘述。

code

D

dp

若没有对每一行循环左移操作,则就是一个普通的走迷宫dp

由于每一行最多只会移动m1次,而n,m<=200,所以可以猜测是一个状态表示为[][][]dp

状态表示:
g[i][j][k]:(1,1)走到(i,j),且第i行循环移动了k次,最小花费。
f[i][j]:(1,1)走到(i,j),最小花费。

考虑状态转移(此题重点):
由于每次只会向右或向下移动一格,所以(i,j)的状态只会从(i1,j)(i,j1)转移过来。

但由于引入了可对行循环左移的操作,使得这两种转移的方式并不一样:

1.(i,j1) -> (i,j) : 由于题目明确要求必须在开始移动之前才能做循环左移操作,故对于行内的转移来说,必须要从当前行移动次数相同的状态转移过来。即:

g[i][j][k] <- g[i][j-1][k] + a[i][j`]

其中a[i][j]表示第i行向左移动了k次后(i,j)位置的数字

2.(i1,j) -> (i,j) : 由于只能对行操作,因此行与行之间的转移其实是独立的。即从一行向下移动到另一行时,状态转移与当前行的循环移动次数是无关的。因此:

g[i][j][k] <- f[i-1][j] + k * w + a[i][j`]

f的转移即为:

f[i][j] = min(g[i][j][0到m-1])

code

E

交互 + 二分,个人感觉非常不错的一道题。

首先要想明白一点:由于1的位置不确定,所以每一次询问的真假性也是不确定的。所以要想办法破掉这个牢笼,让每一次询问的真假性得以确定,从而获得有用信息。

假设这段区间中没有1,即为全0区间,则我们可以知道,0一定是真的回答,1一定是假的回答,因为所有区间的和均为0。这样区间长度与回答之间就具有了二段性:越长的区间回答越容易假,越短的区间回答越容易真。通过二分,就可以在O(logn)时间内确定出k

所以可以考虑:确定出来1在哪个子区间内,这样其余的区间就全0了。可以利用上述方法确定k的值。

具体地,可以确定出1是在整个序列的前一半还是后一半:即为官方题解的做法,通过询问21/4长度区间方法确定出了1的分布,自己确实想不到qwq...

同样,对含有1的那一半区间再询问1次,即可以确定出kn/2的大小关系。

这样,就将区间分为了两半:一半全0,一半含有一个1

此时又分为两种情况:

  1. k<=n/2:直接对长度为n/2的全0区间二分,原理和上面说的一样。
  2. k>n/2: 由于全0区间长只有n/2,故只用全0区间时只能对k<=n/2的情况进行判断。那么k>n/2时怎么办呢?有个巧妙的办法:将另一半含1区间和该全0区间的子区间结合,这样构造的区间和一定为1,并且区间长度范围是[n/2+1,n]。这样就转化为了和上述一模一样的做法,同样具有二段性,二分即可。

code

posted @   jxs123  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
点击右上角即可分享
微信分享提示
主题色彩