NOIP 模拟赛:2024-11-04
T1:
给定一个二叉树,要求给结点赋值 0/1,使其先序遍历得到的二进制数,减去后序遍历得到的二进制数 最大。
对于一个数 \(i\),它取不取只和它的两个序列中的位置大小关系有关。求出序列,然后依次判断即可。复杂度 \(O(n)\)。
T2:
给定一张图,要求选定一个参数 \(K\):若点 \(u,v\) 无边且 \(deg[u]+deg[v]\ge K\),则可以在 \(u,v\) 之间连边。问如果要连成完全图,\(K\) 最大是多少。
一个显然的贪心是每次挑 \(deg[u]+deg[v]\) 最大的一对连边。是 \(O(n^4)\) 的。
维护 \(mx[i]\) 表示与 \(i\) 无边的点中,度数最大的是哪个,这样查找最大的对就只需要 \(O(n)\),而连边后的更新是 \(O(n)\) 的。所以复杂度 \(O(n^3)\)。
T3:
给定平面上 \(n\) 个第一二象限的点 \(a_1\sim a_n\),和 \(m\) 条在第一二象限内的水平线段 \(l\)。询问 \(q\) 次,每次给出一个第三四象限的点 \(p\),询问有多少个点与 \(p\) 的连线不经过任何一条线段(包括端点)。
\(n,q\le 4\times 10^4,m\le 5\)。
先考虑简单版:一条直线。
问题:两个点 \(p,q\)(一个 \(y>0\),一个 \(y<0\))、一条线段 \(l\),若连线过直线,需要满足什么条件。
记 \(r(p,l)\) 为 "以 \(p\) 为投影中心,\(l\) 在 \(x\) 轴上的投影"。
注意到:\(p,q\) 连线过 \(l\) 的等价条件为 \(r(p,l)\) 包含 \(r(q,l)\)。
事实上,\(r(p,l)\) 和 \(r(q,l)\) 只有三种关系:\(r(p,l)\) 整体在 \(r(q,l)\) 左/右侧;\(r(p,l)\) 包含 \(r(q,l)\)。不可能 \(r(q,l)\) 包含 \(r(p,l)\),因为 \(y_p>0,y_l>0,y_q<0\)。
因此,预处理 \(r(a_1\sim a_n,l)\),然后对于询问 \(p\),只需要计数有多少个区间包含 \(r(p,l)\) 即可。一种简便的方法是计数有多少个区间整体在 \(r(p,l)\) 的左/右,然后 \(n\) 减去它,因为上面三种情况是不相交的。
那 \(m\) 条直线呢?因为 \(m\) 很小,直接套一个容斥上去即可。
T4:
这是一个关于宝石的游戏,每一个宝石有两个属性:类型和等级。类型有四种,我们用 \(ABCD\) 来表示,等级是一个正整数:我们用 \(A(4)\) 来表示一个四级的 \(A\) 类宝石,其余的以此类推。
初始游戏生成了一个长度为 \(n\) 的宝石序列,第 \(i\) 个宝石的类型是 \(t_i\),等级是 \(0\),保证不存在连续的三个位置 \(i-1,i,i+1\) 满足 \(t_{i-1},t_i,t_{i+1}\)相等。
玩家可以进行任意轮数的操作,每一轮的流程如下:
-
玩家自由选择是否结束游戏,如果只有一个宝石剩下,那么必须选择结束游戏。
-
玩家自由选择一个位置 \(i\),把当前从左到右第 \(i\) 个宝石给删除,这时右侧的宝石会向左补齐。
-
宝石会发生合并。如果当时存在三个连续的位置 \(i-1,i,i+1\),这三个位置上的宝石类型和等级都一样,那么这三个宝石会合并:这三个宝石会被移出游戏,并且在它们原来的位置会加入一个类型相同,等级加一的宝石。接着右侧的宝石会向左补齐,如果补齐后还存在这样的 \(i\),那么就会发生连锁反应持续合并,直到不存在连续的三个完全相同的宝石位置。需要注意的是,如果某一时刻 \(i\) 的取值不唯一,那么游戏会选择最小的下标 \(i\) (即最左侧的相同的宝石)进行合并。
现在给出一个初始的宝石序列,问一共有多少种不同的结束状态。
两个结束状态是不同的,当且仅当它们剩下的宝石数量不同或者存在一个位置 \(i\) 满足第 \(i\) 个位置的两个宝石不同。
\(n\le 10^6\)。
容易想到我们直接决策最终的宝石序列,而不决策每一步删除哪个宝石。
而一种宝石升一级,需要 \(3\) 个;初始只有 \(0\) 级宝石,所以所有可能出现的宝石个数是 \(O(\log n)\) 种的。
粗略的想法是 \(dp[i][k][0/1]\) 表示用前 \(i\) 个原序列宝石,此时最终序列末尾的宝石决定为 \(k\),且是/否重复了两个 \(k\)。
我们发现这个状态定义极其难去重:因此采用极端值原理,把所有最终宝石序列都只在它第一次能凑出来的位置统计。也就是 \(dp[i]\) 统计 "前 \(i-1\) 个凑不出,前 \(i\) 个才能凑出" 的最终宝石序列。
转移则枚举下一颗最终序列宝石。可以预处理 \(p[i][k]\):表示从 \(i+1\) 开始拿宝石,第一次凑齐一颗 \(k\) 宝石的材料的位置。比如 \(p[i][A2]\) 就是 \(i\) 之后第 \(3^2=9\) 颗 A 类宝石的位置。
这里有一个非常非常隐蔽的问题:我们统计了一种不合法的情况!
如果我们从 \(dp[i][A5]\) 转移到 \(dp[?][A4]\),我们不能从 \(i+1\) 开始拿 \(3^4\) 个 A 进行转移:因为如果这 \(3^4\) 个 A 是紧接 \(i+1\) 开始排列的,我们为了避免它们跟之前决策过的最终宝石合并,需要全部删掉。
所以如果同类宝石从高级转移到低级,需要找到 \(i\) 之后第一个和这一类宝石不同的位置,然后从这个位置开始再取对应数量的类型宝石。
然后发现第二个问题:状态定义 \(O(n\log n)\),转移枚举下一颗宝石 \(O(\log n)\),总复杂度是 \(O(n\log^2 n)\) 的。
注意到把所有转移分成三类:转移到 不同类的宝石/同类且同级的宝石/同类且低级的宝石,用前缀和优化分三类转移即可。