BZOJ3156 防御准备

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3156

Description

Input

第一行为一个整数N表示战线的总长度。

第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai。

Output

共一个整数,表示最小的战线花费值。

斜率优化DP

注意这道题顺序是倒着的

交了好多次都WA,查明原因是把一个名为 calc 的函数的类型打成了 int,本来应该是 long long

从教主的代码中得到启示,要将方程化为适当的形式,以“换元”的方法增强代码的易读性。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #define rep(i,l,r) for(int i=l; i<=r; i++)
 7 #define clr(x,y) memset(x,y,sizeof(x))
 8 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
 9 using namespace std;
10 typedef long long ll;
11 const int maxn = 1000010;
12 ll n,m,head,tail,a[maxn],f[maxn],q[maxn];
13 inline ll read(){
14     ll ans = 0, f = 1;
15     char c = getchar();
16     for(; !isdigit(c); c = getchar())
17     if (c == '-') f = -1;
18     for(; isdigit(c); c = getchar())
19     ans = ans * 10 + c - '0';
20     return ans * f;
21 }
22 inline ll calc(ll x){
23     return (f[x] << 1) + x * x;
24 }
25 int main(){
26     n = read();
27     rep(i,1,n) a[i] = read(); a[0] = 0;
28     f[n] = a[n]; head = 0; tail = -1;
29     q[++tail] = n;
30     for(int i=n-1; i>=0; i--){
31         while (head < tail && calc(q[head]) - calc(q[head+1]) >= (q[head] - q[head+1]) * (i<<1|1)) head++;
32         int j = q[head];
33         f[i] = f[j] + a[i] + (((j-i)*(j-i-1)) >> 1);
34         while (head < tail && (calc(q[tail-1]) - calc(q[tail])) * (q[tail] - i) <= (calc(q[tail]) - calc(i)) * (q[tail-1] - q[tail])) tail--;
35         q[++tail] = i;
36     }
37     printf("%lld
",f[0]);
38     return 0;
39 }
View Code
原文地址:https://www.cnblogs.com/jimzeng/p/bzoj3156.html