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;
}
```\]