首页 > 代码库 > BZOJ3156 防御准备

BZOJ3156 防御准备

我去什么破题跳调了我一个半小时。

不是裸的斜率优化吗。。。我去我去我去我去我去我去!

 

首先我们倒着读进来,然后就省略了倒过来做的问题。

然后写出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 }
View Code

(p.s.   rank3是我小号~~rank4是我自己,还是蛮快滴!Oh耶)

BZOJ3156 防御准备