我去什么破题跳调了我一个半小时。
不是裸的斜率优化吗。。。我去我去我去我去我去我去!
首先我们倒着读进来,然后就省略了倒过来做的问题。
然后写出DP方程:
令f[i]表示选i作为塔时1到i的总代价,则
f[i] = min(f[j] + w(i, j) + a[i]) 其中有j < i 且 w(i, j) = (j - i - 1) * (j - i) / 2
整理可得到f[i] = g[j] + cost[i] - i * j的形式,于是
斜率优化即可。然后沙茶的我就开始了调程序之旅~~~我去。
1 /************************************************************** 2 Problem: 3156 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:1532 ms 7 Memory:28152 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 typedef long long ll; 15 const int N = 1000005; 16 ll a[N], f[N], g[N], ans; 17 int n, l, r, q[N]; 18 19 inline int read(){ 20 int x = 0; 21 char ch = getchar(); 22 while (ch < '0' || ch > '9') 23 ch = getchar(); 24 while (ch >= '0' && ch <= '9'){ 25 x = x * 10 + ch - '0'; 26 ch = getchar(); 27 } 28 return x; 29 } 30 31 inline ll calc_f(ll i, ll x){ 32 return (ll) g[x] + a[i] - i * x * 2 + (i - 1) * i; 33 } 34 35 inline ll calc_g(ll x){ 36 return (ll) f[x] + x * (x + 1); 37 } 38 39 inline ll calc_ans(ll x){ 40 return (ll) f[x] + (n - x) * (n - x + 1); 41 } 42 43 bool pop_head(ll i){ 44 ll x = q[l], y = q[l + 1]; 45 return ((ll) i * (y - x) * 2 >= (ll) g[y] - g[x]); 46 } 47 48 bool pop_tail(ll i){ 49 ll x = q[r - 1], y = q[r]; 50 return ((ll) (g[i] - g[y]) * (y - x) < (ll) (g[y] - g[x]) * (i - y)); 51 } 52 53 int main(){ 54 n = read(); 55 for (int i = n; i; --i) 56 a[i] = read() << 1; 57 f[1] = a[1], g[1] = calc_g(1), ans = calc_ans(1); 58 q[1] = l = r = 1; 59 for (int i = 2; i <= n; ++i){ 60 while (l < r && pop_head(i)) ++l; 61 f[i] = calc_f(i, q[l]); 62 g[i] = calc_g(i); 63 ans = min(ans, calc_ans(i)); 64 while (l < r && pop_tail(i)) --r; 65 q[++r] = i; 66 } 67 printf("%lld\n", ans >> 1); 68 return 0; 69 }
(p.s. rank3是我小号~~rank4是我自己,还是蛮快滴!Oh耶)
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen