您的位置:首页 > 其它

Codeforces Round #250 (Div.1) 解题报告

2014-06-04 15:28 232 查看
一般比赛都是晚上11:30,这次换了时间,所以……就忘了……

A. The Child and Toy

分析:水题。

B.
The Child and Zoo

分析:n最大为10^5,当然不可能真的逐对点考虑。反过来想一想每一条边:什么时候那个小孩会走这条边?特别地,路径最小值在这条边上取到(两个端点中的最小值,可以先做预处理,把点权转换为边权)。使用并查集,一开始每个点自成一集合,我们把边按权值从大到小排序,每一次处理完该边后合并该边端点所在的集合,那么每个集合中的任意点对都是连通的。考虑在处理新的一条边edge(端点为u, v,权值为w)时,假设它的两个端点u, v所在的两个集合分别为S1, S2并且S1 !=
S2。对于任意点a∈S1,点b∈S2,a → u(表示a, u连通,因为a, u属于同一集合), u → v, v → b,故a → b,并且这条路径上的最小值就是w(因为按边权从大到小处理每一条边),所以f(a, b) ≥ w。另一方面,假设f(a, b) = x > w,即是说存在另一条从a到b的路径,这条路径上的每一条边权值都大于w,那么这条路径上的每一条边都会在edge之前被处理,所以集合S1, S2也一定在之前被合并,矛盾。故f(a, b) = w。这意味着,总共至少有2 * |S1| * |S2|个点对(a,
b)满足f(a, b) = w,记这个点对集合为SS(edge)。那么会不会有别的路径漏掉了呢?因为每条路径必有一条最小边,而我们又依次考察了每一条边,故U(SS(edge)) = 全集,其中U表示集合的并。另一方面,由于对不同集合中的点对(a1, b1)和(a2, b2),f(a1, b1) != f(a2, b2),故(a1, b1) != (a2, b2),即SS(edge)两两不相交,于是SS(edge)就是所有点对的一个划分。这就说明了有且仅有2 * |S1| * |S2|个点对(a, b)满足f(a,
b) = w。

C. The Child and
Polygon

分析:用dp[i][j]表示多边形i, i + 1, ..., j, i的划分方法数,那么枚举从顶点i连边的顶点k(可能顶点i不连边),然后递推关系为dp[i][j] += dp[i][k] * dp[k][j]。

D.
The Child and Sequence

分析:单点更新,成段更新,成段求和,第一想法就是线段树。问题是成段更新不是加减运算,而是取模运算,直接做标记不方便处理,于是放弃标记,直接把取模运算处理到叶子结点,最坏情况下要更新[l, r]中每一个数。但是是不是一定要处理到叶子结点呢?不一定的,因为如果a < x,那么a % x = x。也就是说只有当模x不超过a时取模运算才有意义,于是记录每个区间的最大值,如果x大于这个最大值就不必更新这个区间了。如果每次模x都取得很合适,那么最坏情况下是不是还是要更新到每一个叶子结点呢?先抛开单点更新不管,假设m次操作全是成段更新(即取模运算),我们可以分析一下每一个数最多被更新多少次。
设一开始的数列为a[i],经过一次更新后,a[i] = b[i],这意味着b[i] = a[i] % x ≤ a[i] - x,并且b[i] = a[i] % x < x,于是b[i] ≤ min(a[i] - x, x) ≤ a[i] / 2。现在就很清晰了,在只有成段更新的情况下,每个数最多更新log(a[i])次,总时间复杂度为O(nlog(MAX_VALUE))。加上单点更新的情况,最坏情况下每次单点更新都会导致这个数最多被多更新log(MAX_VALUE)次,所以总的不会超过O(mlog(MAX_VALUE)),那么在m,
n同阶的情况下,最终的时间复杂度就是O(nlog(MAX_VALUE))。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: