Board: http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=6832#rank
又是大陆的一场区赛,难度还是大不少
现场围观过,题目解法大部分都知道,重新实现出来,挺有意义的
【第一档】
A 模拟,象棋。
我写过:10分钟无压力。但自己写的还是有点慢的,可能跑去聊了一会天吧,但10分钟还是有压力的 = =
注意两个问题,其实玩过象棋挺好想到的:
1) 将移动时吃了敌方的子 2) 直接飞将
B 很容易看出,如果对于某一天k,在之前第i天生产月饼的代价是 pi + (k - i) * t
那么我们就认为代价是 pi - i * t 咯,在前s天中找一个最小的,这个就是单调队列的事了
C 这是一个典型的水题杂合体
第一步是一个树形DP,求出距每个点最远的点
第二步是一个非常典型的单调队列,非常非常典型,不过好多人都去RMQ超时了
【第二档】
E 笛卡尔树的方法O(n)把二叉树建出来
然后非递归遍历一遍,然后再类似RK的Hash一下
都不难,关键是知道笛卡尔树
F 很好的最小生成树题
需要解决这么一个问题,删掉一条树边时,求出连接两个不相交集合的最小权值边
比较原始的想法是O(N^4) 就是枚举来枚举去的,毋庸多言
好一点的方法是枚举非树边,加到生成树上,形成一个环,更新这个环上的每条边对应的最小值
这个方法最坏是O(N^3)的,但不能每次环上都有这么多边,应该有希望通过
那么再挖掘一下树的性质,删掉一条边(u, v)后,划分为两个不相交集合 S 和 T
很明显,如果以任意S集合的点作为root时,T这颗子树的root一定是v,而在树上可以很轻松求出顶点离以某个点为root的子树的非树边最小距离
先以所有点为root求出这个最小距离,然后枚举删边,枚举S集合的所有点为root时,求一个到 v 的子树的最小距离即可
H 这个题也很好,代码很短,思路是关键
由于可以为实数,那么可以证明,最优解一定是两个人或一个人。(拿三个人出来列个方程)
先去掉一些人K,如果有其他人i满足 p[i].a < p[k].a 且 p[i].b < p[k].b,那么剩下的一定是a降序b升序的。
如果为1个人,那么p[i].a * len <= w。
如果为2个人,要满足 p[i].a * len[i] + p[j].a * len[j] <= w,必然有一个p[i].a * len > w, 否则选那个a比较小的就可以了。
也必然有一个p[j].a * len < w,否则等式不可能成立。这样枚举时就能把N个人分为两类。
咳咳,根据均值不等式,我们可以证明,当两者相等时,积最大。复杂度你懂得。
【第三档】
这一档都是没做的,暂时分一块吧 > <
G 搜索,没写暴力,我看了下,跟北京那个搜索差不多,回忆一下,比较震惊我当时居然敢写 (UPDATED)
D 模拟,有空写了 (UPDATED)
I 几何处理+上下界网络流,都无力啊
J BT 3D几何,无力啊
UPDATE @ 2012-3-26
D 最近写了巨多模拟题,这个算比较弱的了。
首先明确两点以便程序更简洁:
1) 不用记录两个人得分,只记录分差,和当前轮到达这个分差的概率
2) 关于初始出人比速度来决定谁来选人,按速度倒序就可以了,相同的先后顺序不会影响每一轮的输赢,以及最终的结果
那么暴力DFS,走到下一轮的所有可能状态,把概率累加求个最大或者最小的吧。
G 这个真如我当时所说,暴搜
加点很straight的pruning就可以了,brute-force真是一门艺术啊
我加的剪枝就是普通的最优性剪枝,剩余的不同颜色+步数就是估测答案,开始的上界定为联通块数目
剩下两题目测现在没戏搞出了,换题做了 > <