【7.27】代码源 - 【删数】【括号序列】【数字替换】【游戏】【画画】

#703. 删数

题意:给定一个长度为 n ( n ≤ 3 × 1 0 5 ) n(n\leq 3\times 10^5) n(n3×105) 的正整数序列 a 1 , ⋯   , a n a_1,\cdots,a_n a1,,an.

你可以进行若干次操作, 每次操作你可以选择一个位置 i ∈ [ 2 , n − 1 ] i∈[2,n−1] i[2,n1] , 满足 a i = a i − 1 + a i 2 a_i=\frac {a_{i−1}+a_i}{2} ai=2ai1+ai , 然后将 a i a_i ai 删去, 之后的数按顺序向前补空位.

接下来的操作将在新序列上进行.

求若干次操作后, 最终序列的长度最小的是多少.

题解:(差分/倍增)代码源每日一题Div1 删数

思路:方法是一种类似于倍增的 DP 。首先问题等价于对于差分数组,可以合并相邻的相同数,合并后新数是原两数的和,问最小长度。

首先,我们把一个数拆为 a i = d i × 2 c n t i a_i=d_i\times 2^{cnt_i} ai=di×2cnti 。如果两个数可能最终被合并到一个数,那么要满足 d x = d y d_x=d_y dx=dy

我们定义 g ( i , j ) g(i,j) g(i,j) 表示 a i a_i ai 向右合并,最终合并的新数为 d i × 2 j d_i\times 2^j di×2j 的右边界,即 [ i , g ( i , j ) ] [i,g(i,j)] [i,g(i,j)] 合并后的数为 d i × 2 j d_i\times 2^j di×2j 。如果不存在这样的区间则值为 − 1 -1 1 。我们从右向左处理,令 k = g ( i , j − 1 ) k=g(i,j-1) k=g(i,j1) ,如果 [ i , k ] [i,k] [i,k] [ k + 1 , g ( k + 1 , j − 1 ) ] [k+1,g(k+1,j-1)] [k+1,g(k+1,j1)] 区间存在且本质( d d d)相同,那么就可以合并。

最终计算答案的话,定义 f ( i ) f(i) f(i) 表示前 i i i 个数的最小长度,枚举每个数和这个数的向右的拓展点 g ( i , j ) g(i,j) g(i,j) ,把这个区间合为一块,那么递推即为 f ( g ( i , j ) ) = min ⁡ ( f ( i − 1 ) + 1 ) f(g(i,j))=\min(f(i-1)+1) f(g(i,j))=min(f(i1)+1)

AC代码:http://oj.daimayuan.top/submission/305091


#707. 括号序列

题意:给定一个括号序列,计算它有多少非空子段是合法括号序列。 ∣ S ∣ ≤ 1 0 6 |S|\leq 10^6 S106

思路:首先用栈匹配一下。需要知道匹配的一对括号 ( p r e ( i ) , i ) (pre(i),i) (pre(i),i) ,其中间的括号一定是匹配完成且连续的,而且不会出现匹配连起来交叉的情况。那么我们以每个右括号进行 DP,定义 d p ( i ) dp(i) dp(i) 表示 i i i 为右括号的有效括号子串个数,那么 d p ( i ) = 1 + d p ( p r e ( i ) − 1 ) dp(i)=1+dp(pre(i)-1) dp(i)=1+dp(pre(i)1) 。时间复杂度 O ( n ) O(n) O(n)

还有一些 O ( n log ⁡ n ) O(n\log n) O(nlogn) 的做法。把括号序看作分数,分数相同的存到一起。如果两个下标之间最小值大于等于两端分数,则括号序是有效的。用 ST 表解决区间最小值。

AC代码:http://oj.daimayuan.top/submission/305120


#731. 数字替换

题意:维护一个数列,这个数列初始为空。

对于这个数列,总共有 q ( q ≤ 5 × 1 0 5 ) q(q\leq 5\times 10^5) q(q5×105) 次操作,每次操作分为如下两个种类:

1 1 1 x x x ,意为在数列末尾加一个数字

2 2 2 x x x y y y,意为将当前数列中所有值为 x x x 的数的值替换成 y y y

请在 q q q 次操作后,输出这个数列。

题解:(离线)代码源每日一题 Div1 数字替换

思路:容易看出来,操作是对总序列的长度递增前缀进行单数替换。我们可以按照时间逆序来进行替换。为什么要按照时间逆序,是因为越往前的数受到的操作越多,我们逆序的话就能积累下来操作的信息。

这道题我们把所有添加和替换操作按照时间逆序遍历,定义 f a ( x ) fa(x) fa(x) 表示 x x x 要被替换为什么颜色。如果是加数,则添加元素 f a ( x ) fa(x) fa(x) ;如果是替换那么 f a ( x ) = f a ( y ) fa(x)=fa(y) fa(x)=fa(y)

序列操作 挺像的。

AC代码:http://oj.daimayuan.top/submission/305216


#712. 游戏

题意:给定 n × m n\times m n×m 的棋盘,如果存在 k × k k\times k k×k 的子棋盘没有棋子,那么就可以继续放。无法放的输。问先手必胜或必败。

思路:先分析一些状态。我们把一个没有棋子的子棋盘称为空棋盘,如果没有棋子可放,则为必败态。如果所有的空棋盘的交集不为空,那么为必胜态(可以放在交集使得所有空棋盘消失)。如果存在两个空棋盘之外已经放满了棋子,则为必败态(对手可以放在另一个棋盘,使我们必败)。

先特判一次就能结束游戏的情况。然后,初始时一定是所有空棋盘无交集,那每个人的策略是操作完后所有空棋盘的交集仍为空。那么最后的情况就是存在两个空棋盘之外已经放满了棋子的情况,步数为 n × m − 2 × k 2 n\times m-2\times k^2 n×m2×k2 ,判断 n × m n\times m n×m 的奇偶性即可。

AC代码:http://oj.daimayuan.top/submission/305953


#701. 画画

题意:给定矩阵的最终状态,每个格子都有颜色,每次涂色都会将 2 × 2 2\times 2 2×2 的子矩阵染成一个颜色。构造染色方案使得最终结果为给定矩阵。

思路:倒着思考,选择最终染色的地方,然后从这个地方开始 BFS 向四周扩展。注意可能有多个起点。

AC代码:https://codeforces.com/contest/1638/submission/165881216

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值