NOIP 模拟赛:2024-11-04

T1:

给定一个二叉树,要求给结点赋值 0/1,使其先序遍历得到的二进制数,减去后序遍历得到的二进制数 最大。

对于一个数 i,它取不取只和它的两个序列中的位置大小关系有关。求出序列,然后依次判断即可。复杂度 O(n)

T2:

给定一张图,要求选定一个参数 K:若点 u,v 无边且 deg[u]+deg[v]K,则可以在 u,v 之间连边。问如果要连成完全图,K 最大是多少。

一个显然的贪心是每次挑 deg[u]+deg[v] 最大的一对连边。是 O(n4) 的。

维护 mx[i] 表示与 i 无边的点中,度数最大的是哪个,这样查找最大的对就只需要 O(n),而连边后的更新是 O(n) 的。所以复杂度 O(n3)

T3:

给定平面上 n 个第一二象限的点 a1an,和 m 条在第一二象限内的水平线段 l。询问 q 次,每次给出一个第三四象限的点 p,询问有多少个点与 p 的连线不经过任何一条线段(包括端点)。
n,q4×104,m5


先考虑简单版:一条直线。

问题:两个点 p,q(一个 y>0,一个 y<0)、一条线段 l,若连线过直线,需要满足什么条件。
r(p,l) 为 "以 p 为投影中心,lx 轴上的投影"。

注意到: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),因为 yp>0,yl>0,yq<0

因此,预处理 r(a1an,l),然后对于询问 p,只需要计数有多少个区间包含 r(p,l) 即可。一种简便的方法是计数有多少个区间整体在 r(p,l) 的左/右,然后 n 减去它,因为上面三种情况是不相交的。

m 条直线呢?因为 m 很小,直接套一个容斥上去即可。


T4:

这是一个关于宝石的游戏,每一个宝石有两个属性:类型和等级。类型有四种,我们用 ABCD 来表示,等级是一个正整数:我们用 A(4) 来表示一个四级的 A 类宝石,其余的以此类推。

初始游戏生成了一个长度为 n 的宝石序列,第 i 个宝石的类型是 ti,等级是 0,保证不存在连续的三个位置 i1,i,i+1 满足 ti1,ti,ti+1相等。

玩家可以进行任意轮数的操作,每一轮的流程如下:

  1. 玩家自由选择是否结束游戏,如果只有一个宝石剩下,那么必须选择结束游戏。

  2. 玩家自由选择一个位置 i,把当前从左到右第 i 个宝石给删除,这时右侧的宝石会向左补齐。

  3. 宝石会发生合并。如果当时存在三个连续的位置 i1,i,i+1,这三个位置上的宝石类型和等级都一样,那么这三个宝石会合并:这三个宝石会被移出游戏,并且在它们原来的位置会加入一个类型相同,等级加一的宝石。接着右侧的宝石会向左补齐,如果补齐后还存在这样的 i,那么就会发生连锁反应持续合并,直到不存在连续的三个完全相同的宝石位置。需要注意的是,如果某一时刻 i 的取值不唯一,那么游戏会选择最小的下标 i (即最左侧的相同的宝石)进行合并。

现在给出一个初始的宝石序列,问一共有多少种不同的结束状态。

两个结束状态是不同的,当且仅当它们剩下的宝石数量不同或者存在一个位置 i 满足第 i 个位置的两个宝石不同。

n106

容易想到我们直接决策最终的宝石序列,而不决策每一步删除哪个宝石。
而一种宝石升一级,需要 3 个;初始只有 0 级宝石,所以所有可能出现的宝石个数是 O(logn) 种的。

粗略的想法是 dp[i][k][0/1] 表示用前 i 个原序列宝石,此时最终序列末尾的宝石决定为 k,且是/否重复了两个 k

我们发现这个状态定义极其难去重:因此采用极端值原理,把所有最终宝石序列都只在它第一次能凑出来的位置统计。也就是 dp[i] 统计 "前 i1 个凑不出,前 i 个才能凑出" 的最终宝石序列。

转移则枚举下一颗最终序列宝石。可以预处理 p[i][k]:表示从 i+1 开始拿宝石,第一次凑齐一颗 k 宝石的材料的位置。比如 p[i][A2] 就是 i 之后第 32=9 颗 A 类宝石的位置。

这里有一个非常非常隐蔽的问题:我们统计了一种不合法的情况!

如果我们从 dp[i][A5] 转移到 dp[?][A4],我们不能从 i+1 开始拿 34 个 A 进行转移:因为如果这 34 个 A 是紧接 i+1 开始排列的,我们为了避免它们跟之前决策过的最终宝石合并,需要全部删掉。
所以如果同类宝石从高级转移到低级,需要找到 i 之后第一个和这一类宝石不同的位置,然后从这个位置开始再取对应数量的类型宝石。

然后发现第二个问题:状态定义 O(nlogn),转移枚举下一颗宝石 O(logn),总复杂度是 O(nlog2n) 的。

注意到把所有转移分成三类:转移到 不同类的宝石/同类且同级的宝石/同类且低级的宝石,用前缀和优化分三类转移即可。

posted @   FLY_lai  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示