Educational Codeforces Round 80 (Rated for Div. 2) (A-E)

Educational Codeforces Round 80 (Rated for Div. 2)

A
基本不等式。为了规避麻烦的边界处理直接暴力从1搜到 2 ∗ n 2*\sqrt n 2n 是肯定没有问题的。

B
将数码表示转化为数值表示,化简后易知b的形式为 1 0 k − 1 10^k-1 10k1,求得k后乘上A即得答案。

C
容易注意到两个序列的对称性,所以最先考虑到的是如何求解长度为m、最高到达M的不减序列的个数,那么另一边只需要将高度对应的变为n + 1 - M即可。当推了一阵子的递推式后感觉这个形式不太像是数学推导题,又注意到题目的范围,那么 O ( n 2 ∗ m ) O(n^2*m) O(n2m)的dp算法就显而易见了。不过场上我设置的dp[i][j]表示长度为i、最高到达j的序列们的个数,需要枚举第一个到达j的位置k,然后再枚举之前i-1长度的序列最高到达的高度,时间复杂度会成为 O ( n 2 ∗ m 2 ) O(n^2*m^2) O(n2m2),为此我还设置了一个sum[i][j]记录长度为i、最高高度maxH<=j的序列们的个数来优化时间复杂度,如是可以在 O ( n 2 ∗ m ) O(n^2*m) O(n2m)下完成递推。

更好的办法
设置dp[i][j]表示序列中第i个数设置为j,那么递推式为
d p [ i ] [ j ] = ∑ k = 1 j d p [ i − 1 ] [ k ] dp[i][j] = \sum_{k=1}^{j}dp[i-1][k] dp[i][j]=k=1jdp[i1][k]
这个递推式可以用一维数组倒序滚动优化空间花费;可以再开设一个前缀和数组在 O ( m ∗ n ) O(m*n) O(mn)的时间下完成全部更新。

组合数学
能用组合数学的方法解决这道题的关键在于,要将两串m序列等效为一串单调不减的2m序列。只要构造出一个2m序列就可以中间切一刀将其转化为两串m序列,因而我们只需要考虑单调不减的2m序列的所有个数。
因为每个元素取自1到n,所以我们可以设Ci表示2m序列中i出现的个数,进而有
∑ i = 1 n C i = 2 m \sum_{i=1}^nC_i = 2m i=1nCi=2m
根据隔板法可知,其种数为 ( n + 2 m − 1 n − 1 ) {n+2m-1} \choose {n-1} (n1n+2m1).
精妙!

D
Educational Codeforces Round 80 D E
尽管注意到了二分与最大只有8的小m,但是还是不知道该如何检验是否可以构造最小值为x的合并序列。
看了题解后确实学到一种新方法:
对于每一个待检验的x,我们将n个序列转化为n个长度为m的01串,某位为1则代表该位原本的元素是大于等于x的。那么我们要找满足题意的两个序列就等价于找两个对应的01串s、t使得 s ∣ t s|t st全为1。这里有一个巧妙的地方在于,不把n个序列作为比较的元素,而是把等价的另一方面即01串作为比较的元素;我们二重循环遍历所有的01串,如果两个串均可以由某个序列获得,并且其或之和为全1串,那么即可认为对x的检验成功。
其思想可以概括为将2e5的序列集合映射到256的字符串集合上,通过对256的字符串集合搜索就可以等价的得知原集合中是否有满足题意的两个序列。

坑点
被test35WA了(全0数据)…因为我把答案的更新设置在了check函数成功的语句块中,但是并没有保证check函数一定会成功!应该根据这种情况再考虑答案的边界处理!
从而,以后若是遇到在check函数中更新答案的情况一定要注意更新答案是否对于任意数据情况都会运行至少一次!

AC代码

E
同样学习于上一题的博客中…另外看到一个主席树做法怕了怕了…

读完题目后感觉不是特别难…自己尝试写了一下然后假了一下午…呜呜没视力不仔细以为m个数字只可以出现一次…

看了题解后,感觉自己的想法总体上是有一点道理但是自己并不是很会实现。

最小位置没什么新奇之处,最大位置的求解有一些值得学习的地方。
一方面,因为仅将m个数字提前,那么我们开设一个2 * maxn的BIT数组,将n个元素存放在m + 1到m + n的位置上,虚设前m个位置。
另一方面,初始化1-n的自然数序列后,之后每遇到一个元素,应该先更新当前元素到达的最大值,再更新该元素在BIT中的贡献,这是因为:考虑m长度的序列,如果某个数字是第一次出现,那么显然只需要考虑之前比他大的出现的无重元素个数,再加上本身在自然数序列中的位置,而其本身位置其实就可以看作是BIT中加入的若干的元素,所以这也就等价为查询BIT的前缀和;而如果某个元素出现了不止一次,那么在之前那一次出现后其被提升到序列部,在这两个元素之间的其余无重元素都会将该元素往后推一格,并且他们在BIT我们都从后往前进行贡献,所以我们也只需要用前一次出现位置的BIT前缀和来更新该元素的最大距离即可。而统观这两种情况,其表述方式虽然不尽相同,但都可以直接用BIT查询前缀和进行求解,这就为我们提供了理论依据。
如果m序列并没有完全包含所有n个数字,那么剩下的数字所能到达的最远距离一定是所有的消息都被提前后那些剩下数字被推到的位置,因而在处理完m序列后一定要再次更新一下1-n的最远距离。

更新一个BIT的板子问题
以前用的添加、查询函数都是带有上限n的BIT,从一定程度上来说可以降低多组数据的时间复杂度。但是对于单组数据测试其实可以在函数的形参处予以简化处理 ,即将n直接取为maxn。

AC代码

你可能感兴趣的:(ACM)