CF1849

传送门

A

B

在吃了五次罚时后,我终于放弃了卡常优先队列,并发现:把余 0 看作余 k,答案就是余数从大到小排列的,每种余数内部又按照下标排序。

C

我为什么没想到哈希?自我检讨:见到关于字符串判定相等/不同个数时,一定要尝试用哈希!!!

记前缀 [0,i) 的哈希值为 fi,全为 1 的前缀 [0,i) 的哈希值为 gi[0,i)1 的个数为 hi

设排序的区间为 [l,r),则新哈希值为 fnfr+fl+grg[r(hrhl)]

std::set 维护即可。


非哈希做法:

对每个位置求出它左边(包括它)的第一个 0 和右边(包括它)的第一个 1。存在两个数组 lf,rg 里面。

对于一个修改区间 [l,r],它真实改动的部分其实是 [rgl,lfr]。如果这两个元素设定为不存在,那么就没有修改。

把每对 (rgl,lfr)set 维护。

D

贪心法:先有一个错误但是有启发性的贪心:先把所有 2 涂黑,然后标记所有 2 边上的,再把剩下的涂黑。

这是错的,比如 0 2 1 2 0,把第一个 2 涂黑之后可以传递过去。

于是想到把一段连续非 0 的数合并为一个块。 这一段只需要一个硬币。

如果一个块内有 2,这个块左右两边的两个都能被涂黑;如果只有 1,那只有一个能被涂黑。

模拟即可。

dp 法:

dpi 表示涂黑前 i 个的最小硬币数。

基本的,dpi+1=min(dpi+1,dpi+1).

a[i+1]=1dpi+2=min(dpi+2,dpi+1)

a[i+2]=1dpi+2=min(dpi+2,dpi+1)

a[i+1]=1dpi+2=min(dpi+1,dpi+1)

a[i+1]=2dpi+2=min(dpi+2,dpi+1)

a[i+2]=2dpi+2=min(dpi+3,dpi+1)

答案为 min(dpn,dpn+1).

E

朴实无华的题面:有多少个区间最大值在最小值右边。

先单调栈求出每个数左右两边第一个比他大/小的位置。

ai 左边第一个比它大的位置是 li,右边第一个比它大的位置是 ri,左边第一个比他小的位置 si,右边第一个比它小的位置 ti

按套路,枚举每个 ai 作为区间的最大值。

有两种方法计算这种区间的个数:

  1. 枚举 j:lij<i,求出 ji1 的最小值 p,要求在这个区间内 i 的右边不允许有比 p 小的。(否则最大值 i 就在最小值左边)即右端点 tp不合法,总个数减去不合法个数。

  2. 枚举 j:i<jri,求出 i+1j 的最小值 p。同理,只要左端点 sp合法

注意以上两种方法都需单独考虑 i=j 的情况。

我们枚举 ai 时,根据 ili,rii 的大小选择复杂度较低的方法。便可通过此题。

但是感觉时间复杂度不太对啊?

如果按最大值从大到小枚举,每次在循环 x 时如果是重复循环,区间长度至多是上一次循环 x 时的一半。

为什么呢?假设上一次循环 x 时是枚举到 ai,这次是 aj。(不妨 x 是左端点)

显然应该 j<i,不然因为我们从大到小枚举,有 ai>aj,那枚举 aj 的左端点不应该枚举到 x,因为此时 xi 的左边,违反了上面的方法。

那么就有 x<j<i,注意因为从大到小,所以 rji

我们选择了用枚举左端点的方法,说明 jljrjjij.

那也就说明 j 这个位置应该在 [lj,i] 的左半部分,而 x[lj,j],上次 x 被枚举到是和 i 一起,显然应该有 jxix2.

那每个数被枚举到,区间长度至少除以 2,因此复杂度 O(nlogn).

F

5+* 大佬的题解

posted @   FLY_lai  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示