NOIP 模拟赛:2024-11-6

T1:

给出数组 f[1m],表示 "长度 i 的 LIS 的末尾最小元素"(也就是原序列的 LIS 长度为 m)。构造一个长度 n 值域 k 的原序列满足 f 的限制,或判定无解。

一种显然的构造方式:把 f 数组整个放到原序列最后 m 个,然后从开头从大往小填。先不断填 k,如果发现再填就会把对应长度的 f 破坏掉,就开始填 k1 ……


T2:

给定一棵树,初始有棋子在根结点。两人轮流操作,A 可以把某叶子染黑,B 可以把棋子挪到相邻结点。问最优策略下,B 能否把棋子挪到一个非黑色的结点。

dp[i] 表示当前棋子在 i,往 i 的子树里走,A 至少提前染黑多少个叶结点才能保证赢。可以 O(n) DP。同时注意 dp[i]max(dp[i],0)


T3:

对于一个字符串 s,定义操作 f(s,ch):在 s 的每个空里都插入一个 ch

给定一个操作序列 c1cn,问 f(f(f(,c1),c2),) 有多少个本质不同的子序列。

反向考虑一种操作 f(s,ch)=s+ch+s,这样操作等价于 cnc1 做一遍。

f[x][y] 表示当前字符串有多少个子序列以 x 开头,且末尾加上 y 之后就不再是子序列。

当两个字符串 s1,s2 合并为 s 时,其 f 的变化:fs[x][y]=kfs1[x][k]fs2[k][y]。(其实就是矩阵乘法的形式)

f 可以看作两次字符串合并。

为了方便,给字符集添加一个不存在的字符 #f[x][27] 记录了所有以 x 开头的子序列个数。

总共 2n 次合并,一次合并 273,总复杂度 O(n×273)


T4:

给定一个 2×n 的网格图,第一行的第 i 个点和第二行的第 pi 个点有连边。pi 构成一个排列。删掉第 i 条边的代价为 wi,同时会把当前所有与它相交的边一起删掉。问删光的最小代价是多少。n2×105

一个观察是,如果最终选择的边是 i1<i2<<ik,则 pi1<pi2<<pik。同时 (ix,ix+1) 之间 不存在数 w 使得 pix<pw<pix+1

为了方便,不妨额外建立 p0=0,pn+1=n+1 两条无代价的边。

由此导出一个 DP:dp[i] 表示考虑前 i 条边全部删光的最小代价,强制 i 删。转移则枚举 j<i 为上一条决定删的边。

这个复杂度是 O(n3) 的。

分治,先递归进左半边求出左半边的 DP 值。然后考虑左半边某个点作为右半边某个点的前置状态做的贡献。再递归进右半边求出右半边的 DP 值。

问题在于中间的。把左右点取出,各自按照 p 排序。同时维护左右两个单调栈,左边的单调栈保证 i 递减,右边的单调栈保证 i 递增。左边的单调栈保证了都有相交,可以用来更新;右边的单调栈保存了所有可能使得不能更新的可能性,即所有会限制左边点更新的点。

两个指针初始指向左右数组的开头,每次从两个指针中取出 p 较小的更新:

  1. 若取出左边的点 x,则在 px 的位置上标记一个 dp[x]。(在 pop 的时候把对应位置标记为 +

  2. 若取出右边的点 x,先 pop,假设此时栈顶的点第一行 =y,则查询 (py,px) 这个区间内所有标记的最小值,然后把 x 加入栈。

用一个线段树即可。

复杂度 O(nlog2n)

posted @   FLY_lai  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 易语言 —— 开山篇
点击右上角即可分享
微信分享提示