照例
好久不刷题不写题解了。想想自己也大三了。看到子楚兄说自己退役的一瞬间,突然发现自己的时间其实也只剩下一年不到了。
到现在ACM连个铜都没拿过,CCPC也是打铁。再不好好刷题再也没时间了。
跟队友开玩笑说明年要拿金。但我真的希望不是玩笑。
刷题,我生命中最美的两个字!
Day 1
T1 toy 玩具谜题
解释
水题,模拟就行。
我取了个巧,把0换成-1,然后乘就可以。
Code
1 |
|
T2 running 天天爱跑步
解释
两天最难的题了吧。一开始想的是骗分。思路是网上看来的。
首先所有的路径一定是从起点经过LCA(最小公共祖先)到达终点,先上后下(也有可能只上或只下)。
于是我们把s到t的路径拆分成s到top(向上)再由top到t(向下)。
如果把节点v深度记为d[v]的话,那么在向上的过程中 时间+深度 是定值d[s]。
同样,向下过程中 深度-时间 是定值d[t]-len(len = d[s]+d[t]-2*d[top],是路径总长度,也是总时间)。
换句话说,对于从s到top这条路径上所有的点v,如果它的观察时间w[v]满足w[v]+d[v] == d[s];同理,向下满足d[v]-w[v] == d[t]-len,那么它的答案数就要+1。
有几个点吧,第一个是LCA,第二个是树的前缀和。
LCA有人说用Tarjan,我比较菜,不会。我能接受的一种O(nlogn)的方法就是开一个f[0..N][0..logN]的数组,f[i][j]表示结点i的第2^j级父节点。这样找LCA的时候就是O(logn)级别的了。
然后说到,在给s到top或者top到t做标记的时候我们是不能遍历一个个做标记的,所以我们先O(1)的做标记。
比如s到top时,我们在s处做+1标记,在top处做-1标记,之后在求结果的时候深搜求子树和。
用两个数组(桶)up[i]、down[i]记录当前搜索路径下定值为i的路径数(为了避免负数,down数组下标需要加上一个MAXN)
然后就没有了。
Code
1 |
|
T3 classroom 换教室
解释
dp,几乎算是模板题。
递推式自己看代码吧。
Code
1 |
|
Day 2
T1 problem 组合数问题
解释
杨辉三角性质+二维前缀和。
Code
1 |
|
T2 earthworm 蚯蚓
解释
一开始用的queue,结果爆常数了。一怒之下开个10^6的数组好了。
由于切的比例p是定值,所以先被切的一定比后被切的长,所以直接把原长排序、再把切下来的两端分别放进两个队列,每次取队首的比,最长的拿来切。
每回合所有的增长转化为被切的两个缩短。需要注意的是切之前要算一下原长再切。
Code
1 |
|
T3 angrybirds 愤怒的小鸟
解释
状压dp。
i看成二进制,由低到高第x位表示第x只猪。0为未击中,1为击中。
先两两初始化出由这两个点确定的抛物线可以击中的所有的猪(击中就或上这一位),然后O(2^n)的dp就可以了。
有几个坑,一个是a有可能大于等于0,另一个是double由于精度的问题等于要用abs(a-b)<EXP的方式判断。
Code
1 |
|