bzoj 1563 [NOI2009]诗人小G 决策单调性+dp

题面

题目传送门

解法

可以得到一个显然的dp方程

\[f_i=min(f_j+(s_i-s_j+i-j-1-L)^p)$ 不妨把后面的东西看成$w(j,i)$ 所以就变成$f_i=min(f_j+w(j,i))$ 可以发现,这个式子满足四边形不等式 1D1D的四边形不等式可以直接通过决策单调性来优化 转移时注意边界 时间复杂度:$O(n\ log\ n)$ ### 代码 ```cpp #include <bits/stdc++.h> #define LD long double #define N 100010 using namespace std; struct Node { int p, l, r; } q[N]; int n, p, L, s[N], g[N]; LD f[N]; string st[N]; LD Pow(LD x, int y) { LD ret = 1; while (y) { if (y & 1) ret *= x; y >>= 1, x *= x; } return ret; } LD calc(int x, int y) { return f[y] + Pow(abs(s[x] - s[y] - 1 - L), p); } int solve(int p, int l, int r, int i) { int ans = -1; while (l <= r) { int mid = (l + r) >> 1; if (calc(mid, p) < calc(mid, i)) l = mid + 1; else ans = mid, r = mid - 1; } return ans; } int main() { ios::sync_with_stdio(false); int T; cin >> T; while (T--) { cin >> n >> L >> p; for (int i = 1; i <= n; i++) cin >> st[i], s[i] = s[i - 1] + st[i].size() + 1; int h = 1, t = 1; q[t] = (Node) {0, 1, n}; for (int i = 1; i <= n; i++) { while (h <= t && q[h].r < i) h++; f[i] = calc(i, q[h].p), g[i] = q[h].p; if (h > t || calc(n, q[t].p) > calc(n, i)) { while (h <= t && calc(q[t].l, q[t].p) > calc(q[t].l, i)) t--; if (h <= t) { int x = solve(q[t].p, q[t].l, n, i); q[t].r = x - 1, q[++t] = (Node) {i, x, n}; } else q[++t] = (Node) {i, i, n}; } } if (f[n] <= 1e18) cout << (long long)(f[n] + 0.5) << "\n"; else cout << "Too hard to arrange\n"; cout << "--------------------\n"; } return 0; } ```\]

posted @ 2018-08-14 22:09  谜のNOIP  阅读(112)  评论(0编辑  收藏  举报