代码源2025贵阳集训复盘

Day2 模拟赛 1

A

直接从后往前维护一个单调栈,取后缀最大值,然后直接更新当前 f ( l , ∗ ) f(l,*) f(l,)

B

不难发现性质,最开始一串相同的字符是无法添加的,只有 t t t s s s 中都包含才满足条件,之后贪心一下,肯定是找到第一个满足条件的子序列,可以通过记录每个数出现位置然后二分寻找,找到之后设最后一个数位置为 i i i,那么最终右端点在 [ r , n ] [r,n] [r,n] 都是可行的。

C

观察到一个长度的区间是在一段时间内能作为旋律的,所以直接枚举长度,看它在哪个时间上不能作为旋律,通过字符串哈希判断,有结论: s ( l , r − l e n ) = s ( l + l e n , r ) s(l,r-len)=s(l+len,r) s(l,rlen)=s(l+len,r) 那么就有长度为 l e n len len 的字串作为旋律,二分一下时间, c h e c k check check 里面直接用字符串哈希判断。

D

∑ j = 1 i x j ≥ 0 \sum_{j=1}^ix_j \ge 0 j=1ixj0 和另一个式子大于零,等价于所有前缀和都在 s 1 ∼ s n s_1 \sim s_n s1sn 之间,也就是等于最大子段和,所以问题变成了把 s n s_n sn 变成最大子段和需要的操作次数,操作等价于每次删掉一个 − 1 -1 1。操作一次一定能使 s n s_n sn 变大,并且最大子段和单调不降,现在就考虑如何使最大子段和不变。首先如果是

DAY2 数据结构 1

CF1474C

我们发现只要确定 x x x 之后就可以顺着推出所有的数,用一个 set 维护一下剩余数,模拟过程中判断是否可行

CF1237D

单调队列稍微搞一下,如果队头大于队尾乘 2 2 2 就不行

P4587

稍微模拟一下,设当前值域为 [ 1 , x ] [1,x] [1,x] 能表示出 [ 1 , s ] [1,s] [1,s] 的数,那么必须存在 s + 1 s+1 s+1,如果不存在,那么神秘数就是 s + 1 s+1 s+1,否则将 [ x + 1 , s + 1 ] [x+1,s+1] [x+1,s+1] 放到值域中,和就变成了 [ 1 , s + s u m x + 1 , s + 1 ] [1,s + sum_{x+1,s+1}] [1,s+sumx+1,s+1],注意到操作次数一定小于 log ⁡ n \log n logn 次,所以可以对于每个区间直接暴力模拟一遍,对于要维护下标区间上值的信息,直接使用主席树维护。

P5268

通过差分拆询问,然后直接通过莫队维护一个 s u m sum sum,拆括号之后一个单项式作为一个询问,每移动一次只会改变一个 c n t cnt cnt

Day3 数据结构 2

CF1208D

直接倒着做,线段树维护区间和。

CF1690G

对于区间类问题直接使用 set 维护起点信息,用二分去查找。

CF1913D

直接 dp,对于子序列的 dp 一般都是设 d p i dp_i dpi 为以 i i i 结尾的维护信息。显然,可以通过单调栈维护前缀最小,考虑 d p i dp_i dpi 能从哪里转移
:第一个小于 a i a_i ai 的数之后的点作为新区间显然都能被删除,还有单调栈中那些点,可以通过往后删删掉。最终答案一定是单调栈中的点,不然做不到以 i i i 为结尾。

CF2000H

相当于查询连续 1 1 1 个数,很类似于最大子段和,维护三个值:当前最大,左侧最大,右侧最大, p u s h _ u p push\_up push_up 的时候合并一下,中间、左边和右边

P7706

非常线段树,直接维护区间信息,考虑把 神秘东西拆解一下,变成 a i − b j a_i-b_j aibj a k a_k ak,或者 a i a_i ai − b j + a k -b_j + a_k bj+ak。然后线段树维护一下这几个 tag。维护最大、最小、 a i − b j a_i-b_j aibj − b j + a k -b_j + a_k bj+ak ,再向上合并

CF1638E

颜色段均摊,合并的时候维护一下原来 s u m sum sum 和新颜色 s u m sum sum 的差,用树状数组区间求和,最后单点查询加上当前颜色的 s u m sum sum

P6617

注意到如果 w − a i w - a_i wai 在前一个 a i a_i ai 之前就是没有意义的,直接设置为 0 0 0。所以只用维护非常少的点:当前点,原来点的后一个相同,原来点后一个 w − a i w-a_i wai,新点后一个相同,新点后一个 w − a i ′ w-a_i' wai

HDU7436

CF813F

线段树分治,在区间维护整个时间段都有的边,然后在线段树上跑 DFS,用可撤销并查集维护联通,如果 l = r l=r l=r 就给 f i n d ( 1 ) find(1) find(1) 打个标记,然后在 merge 和 roll-back 的时候用类似前几题的那个差值方法维护被合并节点的 time。

T-shirt

我们发现如果是对于每一个顾客能买多少是不好维护的,反过来,考虑每个产品能被多少个人买,排给个序,从小到大扫一遍就结束了,问题就变成了快速求解多少个人能买得起 c i c_i ci。考虑平衡树,暴力 s p l i t split split ≥ c i \ge c_i ci 的位置,直接加,但考虑势能分析,平衡树维护的是相对顺序,左边比右边小,所以我们也只用维护一下相对顺序,发现只有 [ c i , 2 × c i − 1 ] [c_i,2\times c_i - 1] [ci,2×ci1] 的人会改变相对顺序,而修改一次会让原来的数变成一半,所以删掉一个数最多只需要 log ⁡ c i \log_{c_i} logci 次,最终修改次数 n log ⁡ V n\log V nlogV

Day5 模拟赛 2

A

非常简单,直接维护

B

从前往后枚举最大值,值域线段树二分维护后面要扔至少多少钱 。

C

不难发现无人机一定是先上升后下降,并且平飞的长度小于等 1 1 1 格,到某个点的时间就是 max ⁡ ( t u + 1 , a [ v ] ) \max(t_u + 1, a[v]) max(tu+1,a[v]),容易发现这个差不多就是最短路,并且因为是一直上升,所以 t u t_u tu 也是等于 u u u 点的高度,直接用 dijkstsra 求,最终查询答案时需要判断从 1 1 1 i i i 的高度是否和 n n n i i i 的高度只相差 1 1 1

D

我们注意到如果一个大区间包含着小区间,要么不管大区间,要么大区间单独成段,所以直接拿出来考虑,然后得到的一堆区间就是不包含的了,所以排序后左右端点都是单调递增的,考虑 dp。 d p i , j dp_{i,j} dpi,j 表示考虑前 i i i 个区间,分成 j j j 段的方案数,所以 d p i , j = max ⁡ { d p k , j − 1 + r k + 1 − l i } ( r k + 1 > = l i ) dp_{i,j} = \max\{dp_{k,j-1}+r_{k+1}-l_i\}(r_k+1 >= l_i) dpi,j=max{ dpk,j1+rk+1li}(rk+1>=li),因为都是单调递增的,所以用单调队列维护一下可以做到 O ( n 2 ) O(n^2) O(n2)。最后再把那些大区间考虑进去,按长度从大到小排个序,由大往小考虑,最终 a n s ans ans 就是前 i i i 个大区间的长度之和 加上 d p n , k − i dp_{n,k-i} dpn,ki

Day5 数据结构 3

CF459D

非常简单,只需要 维护一下类似逆序对的东西就行。

CF1849E

类似扫描线, 去扫 r r r,考虑计算 f ( l , r ) f(l,r) f(l,r) 表示 l ∼ r l \sim r lr 是否满足条件,是如何转移到 f ( l , r + 1 ) f(l,r+1) f(l,r+1) 的,分类讨论;发现只有当 a r + 1 a_{r+1} ar+1 是最大值或最小值才会有影响,单调栈维护前缀最大最小,在线段树上直接区间修改每个 l l l 对应的 f ( l , r ) f(l,r) f(l,r)

CF526F

等价转换成区间连续段,就是一个区间内是连续的,满足 max ⁡ − min ⁡ = r − l \max - \min = r - l maxmin=rl,同前,维护 f ( l , r ) = max ⁡ − min ⁡ − ( r − l ) f(l, r)=\max - \min - (r-l) f(l,r)=maxmin(rl),对于每一项单独维护,最终查询 f ( l , r ) = 0 f(l,r)=0 f(l,r)=0 的个数。考虑转化成图论,对于相邻的数连边,令 f ( l , r ) f(l, r) f(l,r) 为 点 - 边,没更新一个 r + 1 r+1 r+1 点加一,然后相邻的两个对应的边加一。

Day6 字符串

CF176B

不难发现如果 t t t 能还原成 s s s,肯定可以通过一次操作做到,所以一切不等于 s s s 但可以变化成 s s s 的字符串是等价的,于是就有了 d p i , 0 / 1 dp_{i,0/1} dpi,0/1 表示操作 i i i 步后是否是原串的个数,考虑转移,显然 d p i , 0 = d p i − 1 , 1 dp_{i,0}=dp_{i-1,1} dpi,0=dpi1,1 d p i , 1 = d p i − 1 , 0 × ( n − 1 ) + d p i − 1 , 1 × ( n − 2 ) dp_{i,1}=dp_{i-1,0}\times(n-1) + dp_{i-1,1} \times(n-2) dpi,1=dpi1,0×(n1)+dpi1,1×(n2),第一个式子很好理解,对于第二个,含义就是,在 i − 1 i-1 i1 地方是相同的话,

P4824

直接字符串哈希

CF1721E

kmp 自动机板子,其实就是维护 a u t aut aut 表示在第 i i i 个后面加上字符 c c c 最终跑到哪里

CF898F

注意到加数 和 和的长度之差不超过 1。容易发现 b a s e base base 等于 10 10 10,然后直接字符串哈希做,双模数或者随机模数

P8131

首先直接上 manacher,然后就能知道以 i i i 为回文中心的回文串最长是多少,想到贪心,就是左边能删就删、右边能删就删,最终变成一段连续的字符串就是答案,正确性不显然,稍微模拟一下发现是对的。

P4696

发现和 kmp 很像,现在问题就转化成了如何判断子区间相同,因为是个排列,所以有比 x x x 大的数等于比 y y y 大的数,比 x x x 小的数等于比 y y y 小的数,这样其实可以用树状数组来维护了,但是进一步,只要 x x x 的前驱和 y y y 的前驱所在位置相同, x x x 的后继和 y y y 的后继所在位置相同,那么 x x x y y y 就是匹配的,但其实我们并不需要维护 y y y 的前驱和后继的位置,只需要 x x x 的前驱对应的位置在 b b b 数组中的值小于等于 y y y,后继同理,容易发现每个 y y y 都没限制在了和 a a a 数组中 x x x 被限制的一样的位置,所以 x x x y y y 就是匹配的。

DAY7 模拟赛 3

A

拆解式子发现 ⌈ x + y x ∣ y ⌉ \lceil \frac{x+y}{x|y} \rceil xyx+y 是在 1 ∼ 2 1\sim 2 12 之间的,考虑什么时候等于 1 1 1,只有 x , y x,y x,y 的二进制位没有交集的时候才会等于 1 1 1,不然向上取整后会直接等于 2 2 2,注意到二进制下 1 1 1 最多只有 4 4 4 位,所以直接暴力容斥一下。

B

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值