上次做好了这次又差了,诶, A题看题目看了好久,最后乱搞竟然A了,时间浪费了很多,C题只想着暴力出来,结果可想而知,被hack了,竟然有规律,自己还是想得太少。
要多想,多想才能提高自己,学习要注重效率,不然时间用得再多,结果还是老样子。
这次官方的题解很详细,我就当简要总结吧,别人写得太好了。
官方题解链接
当然不要一不会做就去看题解,必须自己好好想想,还有A,B题官方题解有优化,蛮不错的。
A.
一般人都是暴力O(n^2),官方给了优化O(n+m)。
B.
一般人都是O(n), 但如果n是64位整数,必须优化,要用O(1)过。
把答案化简一下,很容易想到,用公式合并一下即可
C.
暴力求解的话,小范围数据会过不了,所以该方法不行。贪心为正解
根据距离公式很容易得出, 两点的横纵坐标不能相等,贪心很容易得出 ans = min(n,m)+1;
ans个点可以是(i, ans-1-i) (0<= i < ans),它们每个点之间的距离必然是sqrt(2)的整数倍。
D.
很好的dp题,想了比较久,很容易想到O(n^5)(小优化O(n^4))的做法,我只想到这,后来没思路就看了官方题解,官方题解给了很详细的思考过程,从O(n^5)到 O(n^4)到O(n*h^3),这样好的官方题解对我们弱菜来说是十分有帮助的,这能启发我们如何思考某一类DP问题。 先想到复杂度高的容易想到的做法,然后根据问题和状态转移的规律,不断优化到合理的时间内。
我个人总结一下:
开这样一个数组dp[n][2][h][h][h],dp[i][g][a][b][c]含义:进行到高度i,3个方向的状态保存在a,b,c,另一个方向保存在i中(方向i上最接近高度i的棒就是棒i), a,b,c表示分别表示目前其所在的方向上放的最接近高度i的棒与高度i的差,特别注意当其为0时表示棒与高度i已经超过了h,该方向上不合法,即不能到达n-h+1 到n。g表示另一个方向上(i方向)的是否合法。
初始化: dp[1][1][0][0][0] = 4 , 有四个方向放法。
状态转移:我们从dp[i][g][a][b][c]出发。
1........i+1这根棒放到n的这一方向上, 高度上升1,所以状态dp[i+1][g][f(a)][f(b)][f(c)]更新。特别注意 当a,b,c其中出现0时,原本就不合法,转移后也为不合法,当出现h-1时,距离为h,之后递推的时候这个状态无用,即也为不合法。其它情况a,b,c三个方向距离都加1,我们可以写成一个函数f(a) { if(!a || a == h-1) return 0; else return a+1; }
2........ i+1这根棒放到a方向上,这时数组中i和a保存的方向会互换,状态转移后,i方向合法性可能会改变,当a >0时显然i方向合法,另还有放入的棒i+1小于高度h时放入也是合法的。a方向的更新(原先保存在方向i上,所以其合法性根据原来方向i上的合法性),若原来i方向上合法g=1,高度变为1,若原来i方向上不合法g=0,现在也不合法,
所以状态dp[i+1][a > 0 || i+1 <= h][g][f(b)][f(c)]更新。
3.........b,c方向更新与a类似。
最后将所有i==n的合法情况相加, 合法条件为 g == 1(i方向合法) || g == 0 && a+b+c != 0 (a, b, c中其中有一个合法)
当然这题可以用滚动数组把内存优化到O(k^3)。
code
E.
大体思路很容易构建, 先贪心构建期望最大时排列, 然后求一下期望。
怎么个贪心呢? 还得从题目条件出发,我们要期望最大,即听歌的时间最长。
每首歌的时间已经固定,我们要期望最大必须让歌听的次数尽可能的大。
基本的是每首歌至少听一遍,如何让歌听的次数变大呢,根据题意,只有遇到不喜欢听的歌才会让听过的歌重复听。
假设i是喜欢的歌,j是不喜欢的歌(i<j), 期望可以加上 l[i]*p[i]*(1-p[j]), 若i,j位置互换,假设不变,则期望可以加上 l[j]*p[j]*(1-p[i])。
比较那个大,就按照大的方案排序。
n 50000, 必须O(n)求期望,求期望必须枚举所有情况,我们可以假设j为不喜欢的歌,对于每首歌i(i<j),这首歌为喜欢的,期望可以加上p[i]*l[i],若为不喜欢,期望不变。
咋一看是 O(n^2),其实对于每个i,增加的期望为 p[i]*l[i] (i < j)所有的和,是线性增加的,O(1)维护一下即可。
code