标签:
最近莫名其妙地喜欢上了用这种格式写各省省选的全套题解= =
今年浙江省选的出题人是算法竞赛界传说级人物陈立杰,看样子他的出题风格很有特点……ABC三题难度是严格递减的,感觉如果在做第一题的时候被卡住的话恐怕连想死的心都有了……
那么我们先从最难的一题开始……= =
给定一棵N个结点的有正的边权、初始点权为0的无根树,进行M次操作,每次将一个点u的权值增加e($0 \leq |e| \leq 1000$),保证任意时刻点权非负。你的任务是在每次操作后找到一个带权重心u,使得所有点到重心的距离与点权的乘积之和最小(即最小化$\sum_{v} dist(u, v) × val_v,并输出这个最小的值。
N, M均不超过${10}^5$.保证每个点的度数均不超过20.
首先我们假设每次操作过后我们可以快速地在线查询以任意一个点为关键点得到的权值和,那么在这种情况下如何求出最小权值?
为了表达方便,我们不妨设当前以点u为关键点求得的权值和为$S_u$,那么我们不难发现这样一个性质:在树上任意两点a, b之间的路径上,$S_u$构成了一个存在极小值的单峰函数。证明也很简单:考虑路径上任意一条边e,设e两端点分别为s, t,两端连接的点集分别为S, T,边权为e.v。则关键点从s走到t的过程中权值和的变化量:$$\Delta = S_t - S_s = (\sum_{u \in S} val_u - \sum_{v \in T} val_v) * e.v.$$ 而在转移的过程中,点t和它的不在链上的后代结点都将从T集合转移到S集合,即 $(\sum_{u \in S} val_u - \sum_{v \in T} val_v)$ 是单调递增的,又由题意得知边权都是正整数,因此函数 $\Delta = S_t - S_s = (\sum_{t \in S} val_u- \sum_{v \in T} val_v) * e.v.$ 的零点区间一定唯一(由于$\Delta$是离散函数,这里“零点区间”指的是左右两侧函数值正负性相反的区间),且左负右正。由于$\Delta$表示的是S函数的增量,那么$\Delta$的零点区间唯一且左负右正就证明了S是存在极小值的单峰函数。
那么我们设点c为我们要求的一个带权重心。考虑树上任意一点u和它到c之间的路径,由于u的S函数取最小值,又由路径上S函数值的单峰性,我们可以证明在从u到c的路径上S值是单调递增的,而相邻两点S值相同当且仅当这两点的S值均为$S_u$,即最小值。最后这点结论可以由“零点区间连续”自然地得出。
有了这条性质,查询最小权值就好办了。我们可以在树上任取一点u将树有根化,判断它的各邻接点的S值是否小于$S_u$。若存在一点v使得$S_v < S_u$,那么根据上面的结论,我们知道答案一定在v所在的子树中,递归查询即可。若不存在这样的点v,那么答案一定是$S_u$。
听起来很爽对不对?然而,如果我们每次在树上“任取一点”,最坏情况下递归的深度可以达到$O(N)$级别,时间复杂度退化得很严重。怎么办呢?我们可以在树上找到一点u,使得以u为根最大的子树的规模最小化(一般称u为这棵树的重心)。那么这样每棵子树的规模都不会超过原树规模的1/2,那么不难证明此时递归查询的深度就成了$O(\log N)$。
再来考虑开头我们假设的我们已经会了的操作——在线查询任意一个$S_u$。
考虑我们刚才建立的重心分治结构。对点v进行修改时,我们可以花费$O(\log N)$的时间更新v所在的每一层分治结构的重心维护的答案(即在分治u维护的答案中增加$dist(u, v) * \Delta val_v$),并记录每层分治结构中的结点对上一层分治维护的答案的贡献。在对点v查询时,先将答案设为v分治中维护的答案,然后向上移动累加答案:在从分治current向它的上一层分治parent移动时,在parent维护的答案中减去current对它的贡献得到$\delta S$,将得到的结果临时当做点v的后代累加进答案。即$Ans = lastAns + \delta S + (Sum_{parent} - Sum_{current}) * dist(parent, v) $,其中$Sum_t$表示t维护的分治结构中所有点权的平凡加和。这样,我们就会做这道题了。
如果我们用倍增LCA法求dist,时间复杂度为$O((N+M) \log^3 N) $,可能有些卡常数。考虑到操作不会改变原树的结构,我们可以在$O(N \log N)$的时间内预处理后通过ST表维护DFS序列来求LCA,总时间复杂度$O((N+M) \log^2 N)$.
给定一个n个点m条边的无向图,每条边的权值在0~1之间随机选取,求这张图的最小瓶颈生成树的瓶颈的期望值。
点数不超过10, 保证无重边且无自环。
由于题目中的最小瓶颈生成树的瓶颈大小是连续变量,我们无法通过简单地枚举答案和概率来求解。不妨这样考虑:设$F_S(x)$表示图中所有小于x的边能使点集S连通的概率。那么点集S的最小瓶颈为x的概率就是$$P_{(ans=x)} = \lim_{\Delta x \to 0} F_S(x+\Delta x) - F_S(x)$$也就是$$P_{(ans=x)} = F_S ‘(x) \mathrm{d} x$$
由期望的定义,我们有:$$E = \int_0^1 x * F_S ‘ (x) \mathrm{d} x$$是个乘积复合函数,我们对它做分部积分:$$E = \left. \left( x \int F_S ‘(x) \mathrm{d} x - \int (x‘ \int F_S ‘(x) \mathrm{d} x) \right) \right|_0^1 $$得到:$$E = \left. \left( x F_S(x) - \int F_S(x) \mathrm{d} x \right) \right|_0^1$$那么$$E = 1 - \left. \int F_S(x) \mathrm{d} x \right|_0^1$$
那么我们只需要用dp求出整个图的F_V函数,再积分一下就可以得到答案了。
点集连通的概率似乎没法直接求?那么我们来考虑相反的情况,点集S不连通的概率。我们可以任选一点$v_0$,枚举它所在的连通块S‘,并计算出S‘与$S - S‘$的割边数量cnt,那么$$F_S = 1 - \sum_{S‘ \ni v_0 \land S‘ \subsetneqq S} (1 - x) ^ {cnt} $$这样就可以求出答案了。
给定一棵N个结点的树,每个结点有一个颜色,求树上的所有路径经过的不同颜色序列的数量。
N不超过100000,保证树上的叶子结点数量不超过20,颜色值不超过10.
一道比较良心的题……保证了叶子结点不超过20个,我们就可以枚举所有的叶子,分别遍历一遍整棵树,对得到的所有序列建立多串后缀数据结构,查询不同的子串数即可。用广义SAM实现起来比较容易。
浙江省队选拔 ZJOI2015 (Round 1) 解题报告
标签:
原文地址:http://www.cnblogs.com/Asm-Definer/p/4470112.html