POJ 2047 Concert Hall Scheduling
Posted in PKU OJ on 四月 7th, 2010 by 纳米 – Be the first to comment04-05:这水题怎么被分类到较难那里啊?!
04-05:好了我想错了……
04-06:终于构造得一个O(nt log t)的算法,依靠树状数组(t为最大天数)
04-07:发现之前改造程序的时候把排序错删了,提交,AC
简单题解:
根据请求的起始时间进行排序(其实起始时间和结束时间都没所谓的)。预处理,把所有时间段压缩为2 – t(所有时刻同时加减一个时刻,可以保持原有相对性。起始时间为2是方便树状数组编写需要)。
方程不好规范地写出了,大家意思意思,设f(x, y)为在某个请求下,音乐厅A[1, x]时间段被占用,音乐厅B[1, y]时间段被占用所能获得的最大利润。请求占用的时间段为[p, q],可获得的利润为w。
有f(q, k) = max ( max{f(p – 1, k0) | 0 <= k0 <= k}, f(q, k) ), 0 <= k <= t
注意:枚举k需要从大到小。
这样,状态总数为O(n * t),如果用普通实现的话,时间复杂度就是O(t),那么总时间复杂度为O(n * t^2),显然会超时。利用树状数组,可以把转移的时间复杂度降为O(log t),所以,总时间复杂度为O(nt log t)。常数有点大,63ms通过。
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | #include <stdio.h> #include <stdlib.h> #include <string.h> const int maxn = 1001, maxd = 369; int n, m, data[maxn][3], pos[maxd][2], row[maxd][maxd]; bool input() { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d%d%d", &data[i][0], &data[i][1], &data[i][2]); data[0][0] = data[0][1] = data[0][2] = 0; return n > 0; } int comp(int x[], int y[]) { return x[0] != y[0] ? x[0] - y[0] : x[1] - y[1]; } int min(int x, int y) { return x < y ? x : y; } int max(int x, int y) { return x > y ? x : y; } int tree_select(int arr[], int w) { int res = 0; do { res = max(res, arr[w]); w -= w & -w; } while (w > 0); return res; } void tree_update(int arr[], int w, int x) { do { arr[w] = max(arr[w], x); w += w & -w; } while (w <= m); } int work() { qsort(data[1], n, sizeof(int) * 3, (int(*) (const void*, const void*)) comp); int mint = 365, maxt = 1, res = 0; for (int i = 1; i <= n; ++i) { mint = min(mint, data[i][0]); maxt = max(maxt, data[i][1]); } mint -= 2; m = maxt - mint; for (int i = 1; i <= n; ++i) { data[i][0] -= mint; data[i][1] -= mint; } memset(row, 0, sizeof(row)); for (int k = 1; k <= n; ++k) { int t0 = data[k][0] - 1, t1 = data[k][1], w = data[k][2]; for (int i = m; i > 0; --i) { int x = tree_select(row[i], t0) + w; tree_update(row[i], t1, x); tree_update(row[t1], i, x); } } for (int i = 1; i <= m; ++i) res = max(res, tree_select(row[i], m)); return res; } int main() { while (input()) printf("%d\n", work()); return 0; } |