NOIP 2023 复盘

过一段时间心态好了再补,或者就搁置了。

感觉第二题很考思维,反正我是想了一整天才想通。

感觉第四题如果熟练掌握板子的话就很好想,除了离散化没有很创新的东西。

赛时总分:100+20+10+36=166(SH-0210 上海二等奖)

代码

code

题解

1. dict

难度评价: 普及- \colorbox{#fe9c11}{\color{#fff}\text{普及-}} 普及-

标签:模拟,排序

对每个字符串桶排序出最小和最大的可能情况,若一个字符串的最小情况小于所有其他串的最大情况即判可,然后对所有字符串按字典序排序即可。

有趣的是,我考场看错题,以为一个字符串中只能交换一次两个元素,但依然能得到正确答案。目前没想到严格证明,但是多方数据(以及直觉)验证是对的。

复杂度 O ( n m log ⁡ n ) \mathcal{O}(nm\log n) O(nmlogn)

2. tribool

难度评价: 提高+/省选- \colorbox{#3498db}{\color{#fff}\text{提高+/省选-}} 提高+/省选-

标签:模拟,搜索,思维

发现1:所有数的被赋值会导致覆盖之前值,但是不消除之前影响。发现2:由 T r u e True True F a l s e False False 组成的反过来也行。

我们考虑假设 1 ∼ n 1\sim n 1n 的初值 a i = i a_i=i ai=i。然后模拟操作的进行,取反记负数, T r u e True True 1 0 5 + 1 10^5+1 105+1 F a l s e False False − 1 0 5 − 1 -10^5-1 1051 U n k n o w n Unknown Unknown 0 0 0。(详见代码)然后记最终值为 v i v_i vi

然后对每一个元素搜索赋值的根源: v i = i v_i=i vi=i 时即为根源。但是过程中会出现不合常理的情况,即 v i = − i v_i=-i vi=i,自己等于自己的反,显然矛盾,这个值只能是 U n k n o w n Unknown Unknown,然后溯源还可能是 T r u e , F a l s e , U n k n o w n True,False,Unknown True,False,Unknown 的常量,需要特判一下。然后溯源操作类似并查集,所以直接路径压缩。

复杂度 O ( n α ( n ) ) \mathcal{O}(n\alpha(n)) O(nα(n))

3. expand

难度评价: 省选/NOI- \colorbox{#9d3dcf}{\color{#fff}\text{省选/NOI-}} 省选/NOI-

标签:思维,dp

不妨设 x 1 < y 1 x_1<y_1 x1<y1。首先要考虑 dp。设 f ( i , j ) f(i,j) f(i,j) 表示序列 x x x 取前 i i i 个,序列 y y y 取前 j j j 个是否可行。若 x i ≥ y i x_i\ge y_i xiyi f ( i , j ) = 0 f(i,j)=0 f(i,j)=0,若 x i < y j x_i<y_j xi<yj,则有 f ( i , j ) = f ( i − 1 , j ) ∣ f ( i , j − 1 ) ∣ f ( i − 1 , j − 1 ) f(i,j)=f(i-1,j)|f(i,j-1)|f(i-1,j-1) f(i,j)=f(i1,j)f(i,j1)f(i1,j1)。容易继续证明,转移方程可以再简化为 f ( i , j ) = f ( i − 1 , j ) ∣ f ( i , j − 1 ) f(i,j)=f(i-1,j)|f(i,j-1) f(i,j)=f(i1,j)f(i,j1)。复杂度 O ( q n m ) \mathcal{O}(qnm) O(qnm)

然后我们考虑优化,若把 n × m n\times m n×m 的网格画出来,不难发现,如果我们设 x i ≥ y i x_i\ge y_i xiyi 的点为障碍,即找是否存在一条从 ( 1 , 1 ) (1,1) (1,1) ( n , m ) (n,m) (n,m) 的只有向下或向右的路径。

我们思考 x m a x , y m i n x_{max},y_{min} xmax,ymin,假设有 x k < y m i n x_k<y_{min} xk<ymin,那么有 ∀ i , x k < y i \forall i,x_k<y_i i,xk<yi。所以 x k x_k xk 这一列(或者是行,这无所谓)皆可转移到;同理考虑 x m a x x_{max} xmax,性质相似。假如不存在 k k k,可以证明不合法。然后这个网格图中有若干行和若干列是完全可以转移的,不完全可转移的是若干矩形块。

进而我们只要考虑 ( 1 , 1 ) (1,1) (1,1) ( n , m ) (n,m) (n,m) 的块能否转移。以 ( 1 , 1 ) (1,1) (1,1) 块举例:考虑同时干这两件事,不断调整 x i x_i xi 到最小, y j y_j yj 最大,不断扩展可到达的最大位置,若离开当前区块则判断可以。贪心正确的理由是 x i x_i xi 到最小, y j y_j yj 最大的情况必然不劣,因为若 x a < x b x_a<x_b xa<xb,那么前者可到达的位置必然包含后者的,所以若这样贪心找不到,那么其他情况也找不到。注意,由于我们这里极力让 x , y x,y x,y 可到达的位置最大,所以处理 ( n , m ) (n,m) (n,m) 时要反过来推才正确。复杂度 O ( q ( n + m ) ) \mathcal{O}(q(n+m)) O(q(n+m))

4. run

难度评价: 提高+/省选- \colorbox{#3498db}{\color{#fff}\text{提高+/省选-}} 提高+/省选-

标签:dp,离散化,线段树

对于 f i f_i fi 表示时间 i i i 不打卡的最大能量值,则有转移: f i = max ⁡ j = i − k − 1 i − 1 { f j + w ( j + 1 , i − 1 ) − d ( i − 1 − j ) } f_i=\max_{j=i-k-1}^{i-1}\left\{f_j+w(j+1,i-1)-d(i-1-j)\right\} fi=j=ik1maxi1{fj+w(j+1,i1)d(i1j)} 其中 w ( l , r ) w(l,r) w(l,r) 表示从 l l l r r r 天都打卡的获取的能量,但是我们不需要直接求出 w ( l , r ) w(l,r) w(l,r),由于其便于扩展,只要在过程中不断维护就可以了。具体来讲,对于一个挑战 ( x i , y i , v i ) (x_i,y_i,v_i) (xi,yi,vi),当遍历到 i = x i i=x_i i=xi 时,我们把 1 ≤ j ≤ x i − y i 1\le j\le x_i-y_i 1jxiyi (左端点到 1 1 1 是正确的,连续小于 k k k 天的限制我们在转移中维护)区间加 v i v_i vi,这样我们可以实时维护 f j + w ( j + 1 , i − 1 ) f_j+w(j+1,i-1) fj+w(j+1,i1)。发现还有一坨 − d ( i − 1 − j ) -d(i-1-j) d(i1j),可以参变分离,将维护内容改为 f j + w ( j + 1 , i − 1 ) + d ⋅ j f_j+w(j+1,i-1)+d\cdot j fj+w(j+1,i1)+dj,区间查询后再 − d ( i − 1 ) -d(i-1) d(i1)

复杂度 O ( t n log ⁡ n ) \mathcal{O}(tn\log n) O(tnlogn)

然后离散化,这题的离散化我觉得挺难的,需要仔细考虑。因为一个挑战从 x i − y i + 1 x_i-y_i+1 xiyi+1 开始,而到 x i x_i xi 就无关了,如果不考虑其他挑战则必然不用将开始时间提前,或将结束时间延后。对于所有挑战这样考虑,发现一个挑战的关键点是 x i − y i x_i-y_i xiyi x i + 1 x_i+1 xi+1(因为转移是不跑步的时间,这样设关键点便于转移)。那么可以离散出 2 m 2m 2m 个关键点,可行。但是我们的转移方程是在时间上的,所以所有时间都要映射回离散的序号。预处理不好,因为转移中的时间不一定一一对应离散的值,需要取大于(或小于)它的第一个离散值。同时以上原因导致 f i = f i − 1 f_i=f_{i-1} fi=fi1 不能保证推出,需要手动维护上一个 f i f_i fi 不跑步的情况。

复杂度 O ( t m log ⁡ m ) \mathcal{O}(tm\log m) O(tmlogm)

记得开 long long 我有个地方忘了转类型,导致调了半天,所以实在嫌麻烦还是 define int long long 吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值