第一眼,我勒个去。。。然后看到n ≤ 300的时候就2333了
首先把时间离散化,则对于一个时间的区间,可以知道中间最大的那个一定要被选出来,然后把区间分成左右两份
于是区间DP就好了,注意用左开右开的区间比较方便2333
如果暴力找区间内最大值是O(n3)的,当然st表就是O(n2logn)的了。。。不过st表辣么难蒟蒻根本不会QAQQQ
1 /************************************************************** 2 Problem: 3928 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:1820 ms 7 Memory:2248 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 const int N = 605; 15 const int inf = 1e9; 16 17 inline int read(); 18 19 struct data { 20 int st, ed, h; 21 data(int _s = 0, int _e = 0, int _h = 0) : st(_s), ed(_e), h(_h) {} 22 23 inline void get() { 24 st = read(), ed = read(), h = read(); 25 } 26 } a[N]; 27 28 int n, tot; 29 int tmp[N], len; 30 int f[N][N]; 31 32 int main() { 33 int T, H, i, j, k; 34 T = read(); 35 while (T--) { 36 n = read(); 37 for (i = 1; i <= n; ++i) { 38 a[i].get(); 39 tmp[i * 2 - 1] = a[i].st, tmp[i * 2] = a[i].ed; 40 } 41 sort(tmp + 1, tmp + 2 * n + 1); 42 tot = unique(tmp + 1, tmp + 2 * n + 1) - tmp - 1; 43 for (i = 1; i <= n; ++i) { 44 a[i].st = lower_bound(tmp + 1, tmp + tot + 1, a[i].st) - tmp; 45 a[i].ed = lower_bound(tmp + 1, tmp + tot + 1, a[i].ed) - tmp; 46 } 47 tot += 1; 48 for (len = 0; len <= tot; ++len) 49 for (i = 0; i <= tot - len; ++i) { 50 j = i + len, H = -1; 51 for (k = 1; k <= n; ++k) 52 if (i < a[k].st && a[k].ed < j && (H == -1 || a[H].h < a[k].h)) H = k; 53 if (H == -1) f[i][j] = 0; 54 else for (f[i][j] = inf, k = a[H].st; k <= a[H].ed; ++k) 55 f[i][j] = min(f[i][j], a[H].h + f[i][k] + f[k][j]); 56 } 57 printf("%d\n", f[0][tot]); 58 } 59 return 0; 60 } 61 62 inline int read() { 63 static int x; 64 static char ch; 65 x = 0, ch = getchar(); 66 while (ch < ‘0‘ || ‘9‘ < ch) 67 ch = getchar(); 68 while (‘0‘ <= ch && ch <= ‘9‘) { 69 x = x * 10 + ch - ‘0‘; 70 ch = getchar(); 71 } 72 return x; 73 }
时间: 2024-10-11 16:38:55