bzoj 3156: 防御准备
3156: 防御准备
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2396 Solved: 1015
[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
Source
基础斜率优化。。
#include<bits/stdc++.h> #define ll long long #define maxn 1000005 using namespace std; struct node{ ll x,y; node operator -(const node &u)const{ return (node){x-u.x,y-u.y}; } }q[maxn],point; int hd,tl,n,a[maxn]; ll f[maxn],xl; inline int read(){ int x=0; char ch=getchar(); for(;!isdigit(ch);ch=getchar()); for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x; } inline ll Xmul(node x,node y){ return x.x*y.y-x.y*y.x; } inline ll calc(node x,ll XL){ return x.y-x.x*XL; } inline void dp(){ q[tl=hd=1]=(node){0,0}; for(int i=1;i<=n;i++){ xl=i<<1ll; while(hd<tl&&calc(q[hd+1],xl)<calc(q[hd],xl)) hd++; f[i]=calc(q[hd],xl)-i+i*(ll)i+a[i]; point=(node){i,f[i]+i*(ll)i+i}; while(hd<tl&&Xmul(point-q[tl],q[tl]-q[tl-1])>=0) tl--; q[++tl]=point; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ a[i]=read(); a[i]<<=1; } dp(); printf("%lld\n",f[n]>>1); return 0; }
我爱学习,学习使我快乐