NOIP Practice Recordings O

这篇博客介绍了几道典型的算法题目,包括数对满足特定条件的计数,数组求和的优化方法,单调队列在求解最佳序列和理想正方形问题中的应用,以及启发式合并在处理颜色段数问题中的策略。通过实例解析,展示了如何运用二分、前缀和、单调队列等数据结构和算法技巧解决问题。
摘要由CSDN通过智能技术生成

Other

luogu1102 数对

  (2022.4 8)

  给你一个长度为 n ∈ [ 1 , 2 e 5 ] n \in [1, 2e5] n[1,2e5] 的数列(数列中的数 a i ∈ [ 1 , 2 30 ] a_i \in [1, 2^{30}] ai[1,230])和一个整数 C C C,然后让你找出这个数列中所有位置不同的两个数 A , B A, B A,B。并统计满足 A − B = C A - B = C AB=C 的数对的个数。

  挺水的一道题。我们把条件转化一下,把 A − B = C A - B = C AB=C 转化成 A − C = B A - C = B AC=B。然后我们只用建立一个 m a p map map m [ a [ i ] ] m[a[i]] m[a[i]] 表示 a [ i ] a[i] a[i] { a } \{a\} {a} 中出现的次数。然后 a n s = ∑ i = 1 n m [ a [ i ] − C ] ans = \sum\limits_{i = 1}^nm[a[i] - C] ans=i=1nm[a[i]C]。就搞定了。

luogu2671 求和

  (2022.4.9)

  现在有一个数组,每个数三个值 ( x , y , c ) (x, y, c) (x,y,c)。分别表示下标,值和颜色。如果我们找到一个三元组 ( i , j , k ) (i, j, k) (i,j,k) 满足 j j j i , k i, k i,k 的等差中项且下标分别为 i i i k k k 的所对应的颜色相同,那么这个三元组就对答案有 ( x i + x k ) × ( y i + y k ) (x_i + x_k) \times (y_i + y_k) (xi+xk)×(yi+yk) 的贡献。求总答案。

  首先我们发现 j j j 其实没啥用,这里只是规定了 i i i k k k 必须奇偶性相同。所以我们考虑单独把能对答案产生贡献的块放到一起。也就是按颜色为第一关键字, x x x 的奇偶性按第二关键字排序。然后分别处理每一块对答案的贡献,然后再加起来就可以了。

  这里以处理第一块对答案的贡献为例(假设第一块的长度为 k k k)。那么这块的贡献就是:

∑ i = 1 k ∑ j = i + 1 k ( x i + x j ) ( y i + y j ) = ∑ i = 1 k ∑ j = i + 1 k ( x i y i + x j y j + x i y j + x j y i ) = ∑ i = 1 k ( ∑ j = i + 1 k x i y i + ∑ j = i + 1 k x j y j + ∑ j = i + 1 k x i y j + ∑ j = i + 1 k x j y i ) = ∑ i = 1 k ( ( k − i ) x i y i + ∑ j = i + 1 k x j y j + x i ∑ j = i + 1 k y j + y i ∑ j = i + 1 k x j ) \begin{aligned} & \sum_{i = 1}^k\sum_{j = i + 1}^k(x_i + x_j)(y_i +y_j) \\ = & \sum_{i=1}^k\sum_{j=i +1}^k(x_iy_i + x_jy_j + x_iy_j + x_jy_i) \\ = & \sum_{i = 1}^k \left( \sum_{j = i +1}^k x_iy_i + \sum_{j = i +1}^k x_jy_j + \sum_{j = i +1}^kx_iy_j + \sum_{j = i +1}^kx_jy_i \right) \\ = &\sum_{i = 1}^k \left( (k - i)x_iy_i + \sum_{j = i +1}^kx_jy_j + x_i\sum_{j = i +1}^ky_j + y_i\sum_{j = i +1}^kx_j \right) \\ \end{aligned} ===i=1kj=i+1k(xi+xj)(yi+yj)i=1kj=i+1k(xiyi+xjyj+xiyj+xjyi)i=1k(j=i+1kxiyi+j=i+1kxjyj+j=i+1kxiyj+j=i+1kxjyi)i=1k((ki)xiyi+j=i+1kxjyj+xij=i+1kyj+yij=i+1kxj)

  然后我们发现只要我们预处理出 x i x_i xi y i y_i yi x i y i x_iy_i xiyi 的前缀和,我们就能 O ( 1 ) O(1) O(1) 处理我们用很大的括号括起来的那一坨式子。这样整个的复杂度就是 O ( k ) O(k) O(k) 的。

单调队列

WOJ4744 最佳序列

  (2022.4.3)

  给定一个长度为 n n n 的数组 a a a。给定 L , R L, R L,R,求所有满足长度大于等于 L L L 小于等于 R R R a a a 的子区间的平均值的最大。

  先二分答案,也就是二分平均值,然后每个数减去这个平均值,这个时候所有和大于 0 0 0 的区间的平均值就肯定大于二分的值。

  统计减去平均值的后序列的前缀和,问题就变成了前缀和在 [ i − R , i − L ] [i - R, i - L] [iR,iL] 区间内是否存在一个数 s j s_j sj 使得 s i > s j s_i > s_j si>sj,然后就是单调队列优化就能做到 O ( n ) O(n) O(n)

luogu2216 理想正方形

  (2022.4.9)

  给你一个 a × b a \times b a×b 的二维数组( a , b ∈ [ 2 , 1 e 3 ] a, b \in[2, 1e3] a,b[2,1e3])。然后再给你一个 n ≤ a , b n \leq a, b na,b,让你在这个二维数组中找到一个 n × n n \times n n×n 的矩形使得这个矩形中的最大值减这个矩形中的最小值是最小的。

  很显然这是一个 R M Q RMQ RMQ 的问题,因为 a a a b b b 不大,而且 n n n 是确定的,所以我们考虑跑 a + b a + b a+b 遍单调队列来处理这道题,具体做法如下:

  我们以 l u o g u luogu luogu 上的样例为例 n = 2 n = 2 n=2,我们先横着跑单调队列求出每一行连续 n n n 个中的最大值。

1 2 5 6 0 17 16 0 16 17 2 1 2 10 2 1 1 2 2 2 → 2 5 6 17 17 16 17 17 2 10 10 2 2 2 2 \begin{matrix} 1 & 2 & 5 & 6 \\ 0 & 17 &16 & 0 \\ 16 & 17 & 2 & 1 \\ 2 & 10 & 2 & 1 \\ 1 & 2 & 2 & 2 \\ \end{matrix} \quad \to \quad \begin{matrix} 2 & 5 & 6 \\ 17 &17 & 16 \\ 17 & 17 & 2 \\ 10 & 10 & 2 \\ 2 & 2 & 2 \\ \end{matrix} 10162121717102516222601122171710251717102616222

  然后再竖着跑单调队列求出每一列中连续 n n n 个数的最大值:

2 5 6 17 17 16 17 17 2 10 10 2 2 2 2 → 17 17 16 17 17 16 17 17 2 10 10 2 \begin{matrix} 2 & 5 & 6 \\ 17 &17 & 16 \\ 17 & 17 & 2 \\ 10 & 10 & 2 \\ 2 & 2 & 2 \\ \end{matrix} \quad \to \quad \begin{matrix} 17 &17 & 16 \\ 17 & 17 & 16 \\ 17 & 17 & 2 \\ 10 & 10 & 2 \\ \end{matrix} 21717102517171026162221717171017171710161622

  同理,我们对最小值也这样处理:

1 2 5 6 0 17 16 0 16 17 2 1 2 10 2 1 1 2 2 2 → 1 2 5 0 16 0 16 2 1 2 2 1 1 2 2 → 0 2 0 0 2 0 2 2 1 1 2 1 \begin{matrix} 1 & 2 & 5 & 6 \\ 0 & 17 &16 & 0 \\ 16 & 17 & 2 & 1 \\ 2 & 10 & 2 & 1 \\ 1 & 2 & 2 & 2 \\ \end{matrix} \quad \to \quad \begin{matrix} 1 & 2 & 5 \\ 0 &16 & 0 \\ 16 & 2 & 1 \\ 2 & 2 & 1 \\ 1 & 2 & 2 \\ \end{matrix} \quad \to \quad \begin{matrix} 0 &2 & 0 \\ 0 & 2 & 0 \\ 2 & 2 & 1 \\ 1 & 2 & 1 \\ \end{matrix} 101621217171025162226011210162121622250112002122220011

  然后将跑出来的两个矩阵相减,找到差矩阵中的最小值即为所求:

17 17 16 17 17 16 17 17 2 10 10 2 − 0 2 0 0 2 0 2 2 1 1 2 1 = 17 15 16 17 15 16 15 15 1 9 8 1 \begin{matrix} 17 &17 & 16 \\ 17 & 17 & 16 \\ 17 & 17 & 2 \\ 10 & 10 & 2 \\ \end{matrix} \quad - \quad \begin{matrix} 0 &2 & 0 \\ 0 & 2 & 0 \\ 2 & 2 & 1 \\ 1 & 2 & 1 \\ \end{matrix} \quad = \quad \begin{matrix} 17 & 15 & 16 \\ 17 & 15 & 16 \\ 15 & 15 & 1 \\ 9 & 8 & 1 \\ \end{matrix} 1717171017171710161622002122220011=17171591515158161611

  答案就是 1 1 1

启发式合并

luogu3201 HNOI2009 梦幻布丁

  (2022.4.11)

  初始给以一个长度为 n n n 的数列,这个数列的每个数表示一个颜色,然后给你 m m m 个操作,每次操作或是查询现在颜色的总段数(例如 1 , 2 , 2 , 1 1, 2, 2, 1 1,2,2,1 就是有 3 3 3 段颜色)或是给定 x , y x, y x,y 表示将颜色 x x x 的数全部变为 y y y 颜色。

  显然这道题就是一个链表的启发式合并,我们维护很多链表,每个链表中存出同一种颜色的数。然后每一次修改就是一次启发式合并,对于询问我们可以在修改的时候处理出来,具体来说就是:如果(假设 x x x 是元素较少的那个集合) x x x 中的一个元素旁边有有 y y y 中的元素的话那么 a n s ans ans 就应该减 1 1 1

  这样虽然看起来很暴力,但是时间复杂度就是启发式合并的时间复杂度也就是 O ( n log ⁡ n ) O(n\log n) O(nlogn) 的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值