bzoj 3156: 防御准备

3156: 防御准备

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 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
",f[n]>>1);
	return 0;
}

  

原文地址:https://www.cnblogs.com/JYYHH/p/8576155.html