Codeforces Round #689 (Div. 2)

img

几乎所有题目都是思维题目,代码不长,如果想看请见提交记录

A. String Generation

题意略

比较简单的构造题目,直接"abcabcabc...."即可保证不会出现长度不超过\(k\)的回文串

B - Find the Spruce

统计矩形方阵中三角形的个数

原来单个的'*'也算在三角形以内了,太淦了

O(\(n^2 \cdot m\))

首先三角形一定都长一样,每一层的'*'分别是\(1,3,5......\),即可通过前缀和统计'*',然后暴力枚举每个顶点,就可\(O(n^2 \cdot m)\)

O(n^2)

在讨论区看到的神奇DP,思路比较巧妙

首先一个性质:除了一个'*'之外,其余的三角形至少是由该点下方的三个'*'构成

定义\(dp[i][j]\)\((i,j)\)点树的数量,转移如下:

if s[i][j] == '*':
    dp[i][j] = min(dp[i+1][j-1], dp[i+1][j], dp[i+1][j+1]) + 1
else:
    dp[i][j] = 0 

答案即为所有\(dp[i][j]\)的和。

这类\(DP\)问题貌似有名字,如果想知道可以去\(CF\)讨论里面看看(我忘记了,\(qwq\))

C - Random Events

给定一个长度为 \(n\) 的数组,给出 \(q\) 个操作 $( r , p ) $ 对$ [ 1 , r ]$区间进行有序排序,排序的概率是 \(p\) ,不变的概率自然就是$ 1 − p $。问最后数组全部有序的概率是多少。

巧妙的贪心

一个性质:一旦数组被排序,它就永远不会未排序。

根据这个思路,可以发现,真正可以影响到整个数组的,其实是\(r\)大于等于最后一个不有序的位置的操作

例如\(n=4,[3,1,2,4]\),有序数组为\([1,2,3,4]\),显然在\(i=3\)的位置是最后不有序,那么\(r<3\)的操作都可以忽略,因为无论他们成功还是失败,这个位置都无序。

D - Divide and Summarize

给出一个数组,你可以操作\(0\)次或若干次改变这个数组。然后给出 \(q\) 个查询,问能不能找到一个数组和等于 \(s\)

具体操作就是选取一个\(mid=[\frac{max(arry)+min(arry)}{2}]\) , 然后小于等于 \(mid\) 放左边数组,大于放右边数组,选择一个数组代替原来的数组

分治思想做法

式子里面只有最大值最小值,直接排序,最小值和最大值肯定是数组区间的第一个和最后一个,\(mid\)的位置也可以通过二分快速找到,就可以快速分割左右两个数组。

很明显这种分割是有限的(每次只能从大于\(mid\)和小于\(mid\)里面选一个),所以对原数组操作产生的所有可能和放在一个\(set\) 里面,查询的时候直接判断时候在里面即可

其他做法

可能有二进制做法,在讨论里面看到的,没看懂什么意思(大雾

E - Water Level

初始在饮水机中有\(k\)升水,每天需要消耗\(x\)升水,每天的一开始,\(John\)可以选择往饮水机中加\(y\) 升水(可以不加)。问\(t\)天内是否能保证每时每刻饮水机内的水大于等于\(l\)升,小于等于$r $升

有解分为两种情况,一种是无限天数都在范围内(循环),另一种是\(t\)天内在范围内

先把\(k-l\),\(r-l\)这样就能忽略掉\(l\)了,不然数据实在太大了,数据除了\(x\),其他都是\(10^{18}\)级别的

分类讨论一下:

\(x>y\),水位每一天都会下降,如果一直加水,每天都会减少\((x-y)\),看看够用几天的(一定要注意前几天能不加水,别加超了)

\(x<=y\),那么有个显然的贪心,让水位尽量低,这样可以给后面留下容错空间(表达不好,将就理解一下)

\(k\)是当前水量,如果够一天的使用,则不加水,如果不够一天的使用则加水

如果\(k+y>r\),无解

如果\(k+y<=r\),这里就要判断一下会不会出现循环的情况(有解),\(k+=y\)然后\(k\%=x\),如果这时候的\(k\)出现过,那就有循环了,有解

如果\(t\)循环到\(0\)了,有解

F - Mathematical Expression

\(2700\)分的贪心+结论+DP,恐怖如斯

给一个长度为\(n(n\le 10^5)\)的序列\(a\)\(0 \le a_i\le 90\),现在给定你可以用\(+,-,*\)中的一些符号填到序列中\(n-1\)个位置上,使得最后的式子运算结果最大,乘法运算优先于加法与减法,请输出最后的式子

首先发现这里面有两个比较特殊的数\(0\)\(1\)

对于\(0\),乘以\(0\)都是\(0\),对于\(1\),乘以\(1\)和没乘一样

先把问题分一下类

  • 只有\(+,-,*\)其中一种

直接放即可

  • \(+-\)两种

对于减法来说只会让答案变小,我们肯定是不用的,所以全用+

  • \(*-\)两种

乘以\(0\)都是\(0\),所以只需要把第一个\(0\)用减号,其他都用乘即可

\(3*2*4*5-0*3*0*5*2\)

注意以后的\(0\)不用减法,因为减去的数越小答案越大

  • \(*+\)或者\(*+-\)

减号显然直接不用,所以这两种是一类

显然,\(0\)的前后都一定是加号,这样我们就可以把序列用\(0\)拆分

拆分后,对于开头和结尾的\(1\),一定是用加号链接,例如$1\ 1\ 1\ 3\ 5\ 10\ 1\ 1\ 1 $

问题变为不含\(0\)且首尾均不是\(1\)的子序列,我们用\(+\)\(*\)使其最大

直接用\(DP\)解决的话,会\(TLE\)

一个神奇结论:

如果当前序列的乘积大于长度\(2*N\)的时候,就直接全部乘法即可。否则里面最多有\(logn\)个数大于\(1\)

问题变为长为\(logn\)的数组,只用加和乘使得答案最大。

有了上面的结论,问题复杂度就可以转化为\(O(nlogn)\)

posted @ 2020-12-14 21:00  pyyyyyy  阅读(87)  评论(0编辑  收藏  举报