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(nle 10^5))的序列(a)(0 le a_ile 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))

$$Life quad is quad fantastic!$$
原文地址:https://www.cnblogs.com/pyyyyyy/p/14135667.html