bzoj1563: [NOI2009]詩人小G 決策單調性(1D1D)
阿新 • • 發佈:2018-10-11
單調性 .com const cst 方程 algorithm tdi com stp
目錄
- 題目鏈接
- 題解
- 代碼
題目鏈接
bzoj1563: [NOI2009]詩人小G
題解
\(n^2\)dp長這樣
\(f_i = min(f_j + (sum_i - sum_j - 1 - L)^P)\)
設\(w_{ij} = (sum_i - sum_j - 1 - L)^P\)
那麽化成1D1D的標準形式
$ f_i = min(f_j + w_{i,j}) $
打個表發現w滿足四邊形不等式
證明可以看這裏
https://www.byvoid.com/zhs/blog/noi-2009-poet
因此狀態轉移方程具有單調性
代碼
#include<cstdio> #include<cstring> #include<algorithm> #define LL long long #define gc getchar() #define pc putchar #define LD long double inline int read() { int x = 0,f = 1; char c = gc; while(c < '0' || c > '9' )c = gc; while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = gc; return x * f ; } void print(LL x) { if(x >= 10) print(x / 10); pc(x % 10 + '0'); } const int maxn = 100007; char s[maxn][32]; int n,L,p; inline LD fstpow(LD x,int k) { LD ret = 1; for(;k;k >>= 1,x = x * x) if(k & 1) ret *= x; return ret; } LD f[maxn]; int sum[maxn]; LD calc(int j,int i) { return f[j] + fstpow(std::abs(sum[i] - sum[j] - L),p); } int find(int x,int y) { int l = x,r = n,ret = 0; while(l <= r) { int mid = l + r >> 1; if(calc(x,mid) >= calc(y,mid)) r = mid - 1; else l = mid + 1; } return l; } int q[maxn],c[maxn]; int pre[maxn]; void solve() { n = read(),L = read() + 1,p = read(); for(int i = 1;i <= n;++ i) { scanf("%s",s[i] + 1); sum[i] = sum[i - 1] + strlen(s[i] + 1) + 1; } int h = 1,t = 1; q[h] = 0; for(int i = 1;i <= n;++ i) { while(h < t && c[h] <= i) ++ h; f[i] = calc(q[h],i); pre[i] = q[h]; while(h < t && c[t - 1] >= find(q[t],i)) t --; c[t] = find(q[t],i); q[++ t] = i; } if(f[n] > 1e18) { puts("Too hard to arrange\n--------------------"); return; } printf("%.0Lf\n", f[n]); puts("--------------------"); } int main() { int T = read(); for(int i = 1; i <= T; ++ i) { solve(); } return 0; }
bzoj1563: [NOI2009]詩人小G 決策單調性(1D1D)