04day2
中位数
排序
【问题描述】
给出 1~n 的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是 b。中位数是指把所有元素从小到大排列后,位于中间的数。n<=100000
【输入】
第一行为两个正整数 n 和 b,第二行为 1~n 的排列。
【解题过程】
看到这个数据范围马上又想到排序了。
可以发现,我们要找的区间满足的条件是区间内大于 b 的数字个数与小于 b 的数字个数相等。如果用 x(i) 表示第 1~i 个数字中大于 b 的数字个数,用 y(i) 表示小于 b 的数字个数,那么我们要找的区间 [L, R] 就会满足如下条件(注意 b 必须在区间 [L, R] 内):
x(R)-x(L-1) = y(R)-y(L-1)
稍作变形可得:
x(R)-y(R) = x(L-1)-y(L-1)
所以我们可以对于每个位置 i,以 val = x(i)-y(i) 为关键字进行排序,那么 val 值相等的元素一定排在一起,所以扫描一遍进行统计即可。对于一片连续的 val 值相等的元素,统计出位置在 b 左边的有 cl 个,位置在 b 右边的有 cr 个,那么这里就能得到 cl*cr 个符合题意的区间。
初次提交 70 分左右。原因是在循环结束之后多做了一次统计。
另外参考 O(n) 算法:http://www.cnblogs.com/vb4896/p/3984329.html
打砖块
动态规划
【问题描述】
在一个凹槽中放置了 n 层砖块、最上面的一层有 n 块砖,从上到下每层依次减少一块砖。每块砖都有一个分值,敲掉这块砖就能得到相应的分值,如下图所示。
14 15 4 3 23
33 33 76 2
2 13 11
22 23
31
如果你想敲掉第 i 层的第 j 块砖的话,若 i=1,你可以直接敲掉它;若 i>1,则你必须先敲掉第i-1 层的第 j 和第 j+1 块砖。
你现在可以敲掉最多 m 块砖,求得分最多能有多少。
【输入】
输入文件的第一行为两个正整数 n 和 m;接下来 n 行,描述这 n 层砖块上的分值 a[i][j],满足0≤a[i][j]≤100。
【解题过程】
这道题想了很久还是没有靠谱的思路。
最初的想法是要打掉一个砖块就必然会打掉一个三角形区域,这个砖块在这个三角形区域的尖端。那么就在状态转移的时候枚举上一次打掉的「尖端」是哪个,但是这样无法确定两个上个状态的区域与当前状态的区域的重叠部分。
然后看了题解。
其实对最终状态分析就会发现,每一列被打掉的砖块必然是从底部开始的连续的一段,即最终形态应该是这样的:
那么我们就可以用 f(i, j, k) 表示在最多打 k 个的限制下,第 i 列一共打了 j 个。在第 i 列打了 j 个的条件下,对于右边列是有限制的(第 i+1 列至少打 j-1 个,第 i+2 列至少打 j-2 个),所以从右往左递推。同样地,注意在 k 的限制下 j 的枚举范围。
初始得分 80 分。漏了 j = 0 的情况。
最小密度路径
最短路
【问题描述】
给出了一张有 N 个点 M 条边的加权有向无环图,接下来有 Q 个询问,每个询问包括 2 个节点 X 和Y,要求算出从 X 到 Y 的一条路径,使得密度最小(密度的定义为,路径上边的权值和除以边的数量)。
【输入】
第一行包括两个整数 N 和 M。
第 2 到第 M+1 行,每行三个数字 A、B、W,表示从 A 到 B 有一条权值为 W 的有向边。
第 M+2 行只有一个整数 Q。
接下来 Q 行,每行有两个整数 X 和 Y,表示一个询问。
1≤N≤50,1≤M≤1000,1≤W≤100000,1≤Q≤100000。
【解题过程】
从 N 和 M 来看,初步把算法锁定在 Floyd。
最小密度路径直接用最短路是不太好求的,在路径长度之外还有路径边数要考虑,那么就可以根据不同的路径边数来考虑。
用 f(i, j, k) 表示从 i 到 j 经过 k 条边的最短路,则可以从 k-1 转移而来,也就是在 Floyd 外面再套一重循环。
初始得分 40 分。按常理 k 应该不超过 n-1,但是 WA 了。把 k 改成从 1~N 枚举就 AC 了。那么可能是有自环的情况,但是这样就不符合题目中有向无环图的限制了。严重怀疑数据有问题。