Markdown Syntax Test
Using plugin PHP-Markdown. Just a test! Read on →
Most is about Olympiad in Informatics
Using plugin PHP-Markdown. Just a test! Read on →
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
有一些错误,比如说树套树的修改复杂度是:O(2*log^2n)
SlideShare(被墙自重): [slideshare id=13746519&doc=k-120724213841-phpapp02]
zip下载:
很容易想到一个很朴素的状态表示,f[i, j, k, l]表示前i个房间住了j个男的k个女的以及l对夫妇。显然TLE+MLE!
现在让我们考虑一下这道题的一些有意思的性质。f[i, j, k, 0] = min { f[i-1, j, k, 0], price[i] + min{ f[i-1, j-p, k, 0], f[i-1, j, k-p, 0] } } f[i, j, k, 1] = min { f[i-1, j, k, 1], price[i] + min{ f[i-1, j-1, k-1, 0], f[i-1, j-p, k, 1], f[i-1, j, k-p, 1] } }时间复杂度O(roommalefemale2),勉强不会超时。但是MLE!解决办法可以:滚动数组,或者跟01背包一样,倒着做,直接覆盖,空间复杂度降到O(malefemale) Read on →
f[i, x, y] = max{ f[i-1, x+s, y] + s } (d[i] = 1) max{ f[i-1, x-s, y] + s } (d[i] = 2) max{ f[i-1, x, y+s] + s } (d[i] = 3) max{ f[i-1, x, y-s] + s } (d[i] = 4)
其中s为0到最远滑行距离,也就是min{第i时间段的时间, 障碍物到当前点的距离}
时间复杂度O(knm*最大时间),其中最大时间<=max(n, m)
优化:
考虑d[i] = 1的情况:
f[i, x, y] = max{ f[i-1, x+s, y] + s } (d[i] = 1) = max{ f[i-1, x+s, y] + (x+s) } - x 令g(k) = f[i-1, x+s, y] + (x+s),那么: f[i, x, y] = max{ g(k) } - x
于是我们可以对于同一个i和y的每一个x,维护一个单调递减的队列,每次取出队头-x就是f[i, x, y]的值。
Read on →一开始想到了在两条之间范围内的直线焦点数,也就是逆序对。但是题目给的是圆,不像两条直线那样可以直接确定在两条直线上的位置,也就无法逆序对……
但是,跟上面有点类似的,这题也可以将直线转化掉。
考虑每一条跟圆相交的直线,它必与圆交于两点,相切的话当作两个相同的点。那么,一条直线就变成了圆上的一段弧。至于是优弧还是劣弧并不重要,原因如下:考虑两条与圆相交的直线A和B,那么把它们两个端点按照极角排序后的顺序只有两种(可以移动):ABAB或者ABBA。显然,只有当出现ABAB这种情况,也就是两条弧相交且不包含时,两条直线相交。那么回到优弧和劣弧的问题上,假设B是优弧还是劣弧确定了,且A的劣弧与B的弧相交,那么A的优弧必与B的弧相交。因此,优弧或者劣弧并不影响结果。
现在,我们就把问题转化成:在数轴上有一些长度不等的线段,问有多少对线段相交且不包含。
解决方法:
称某条直线与圆的2个交点中,按照极角排序后较小的为左括号,较大的为右括号。设数组C[],初始化为0。for i ∈ 所有交点 if i 为某条直线L的左括号 C[i] = 1 else j = i对应的该条直线的左括号 ans += C[j+1]+...+C[i] C[j] = 0
实际上,每一次遇到右括号,就统计出当前直线L与在其左端点以后的直线的相交次数,当所有点做完之后,C[]数组全部为0,ans即为所求的交点数量。
可以用树状数组或者线段树维护区间和。 Read on →1 100 3 100 3 100
这样可以获利300。
接着,在当前时刻,我们肯定先挑利益最大的做。
但是有个截止时间很讨厌。我们不妨把问题转化一下:我们不着急着马上求出最优方案,我们把所有可能在最优工作安排集合当中的工作放在一起,然后逐步修改这个集合,到最后就是最优的安排集合了。
做法如下:
按照截止时间从小到大排序,用小根堆维护所有可能要做的工作。那么堆中的元素个数+1就是当前时间。遍历每一个工作。最后的答案就是把堆中工作相加。
Hint:这题要用long long
P.S.:C++的priority_queue很好用! Read on →比较水的动规。
注意到这题主要的变量就是时间和能力值,而且时间能力值<=10000100,因此空间上能够承受二维的状态。
用f[i, j]表示在第i时刻,能力值为j的情况下,所能滑的最大距离。
每一天最多有三种事情可以做:喝果汁、滑雪,有时还可以上课。怎么计算pre[j]呢?
主程序的复杂度达到了O(t(s+100)),那么预处理采用O(n100)的朴素做法也未尝不可。当然也可以双关键字排序+线性扫描,快不了多少,而且写起来麻烦。
Read on →