bzoj 3156: 防御准备
3156: 防御准备
Time Limit: 10 Sec Memory Limit: 512 MB[Submit][Status][Discuss]
Description
Input
第一行为一个整数N表示战线的总长度。
第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai。
Output
共一个整数,表示最小的战线花费值。
Sample Input
10
2 3 1 5 4 5 6 3 1 2
Sample Output
18
HINT
1<=N<=10^6,1<=Ai<=10^9
枚举上一个守卫塔建在哪儿转移DP
斜率优化
#include<cstdio> #include<iostream> #define N 1000001 using namespace std; long long sum[N],dp[N]; int a[N]; int head,tail,q[N]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } long long up(int k,int j) { return dp[j]-dp[k]+sum[j]-sum[k]; } long long down(int k,int j) { return j-k; } int main() { int n; read(n); for(int i=1;i<=n;i++) read(a[i]),sum[i]=sum[i-1]+i; int j; for(int i=1;i<=n;i++) { while(head<tail && up(q[head],q[head+1])<=down(q[head],q[head+1])*i) head++; j=q[head]; dp[i]=dp[j]+1ll*i*(i-j)-sum[i]+sum[j]+a[i]; while(head<tail && up(q[tail-1],q[tail])*down(q[tail],i)>=up(q[tail],i)*down(q[tail-1],q[tail])) tail--; q[++tail]=i; } printf("%lld",dp[n]); }