【BZOJ3156】—防御准备(斜率优化)

传送门


水题
随便推个式子斜率优化就完了

#include<bits/stdc++.h>
using namespace std;
const int N=1000005;
#define int long long
#define gc getchar
inline int read(){
	char ch=gc();
	int res=0,f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
#define ll long long
#define cs const
#define pb push_back
#define db double
struct pt{
	db x,y;
	pt(db _x=0,db _y=0):x(_x),y(_y){}
	friend inline pt operator +(cs pt &a,cs pt &b){
		return pt(a.x+b.x,a.y+b.y);
	}
	friend inline pt operator -(cs pt &a,cs pt &b){
		return pt(a.x-b.x,a.y-b.y);
	}
	friend inline db operator *(cs pt &a,cs pt &b){
		return a.x*b.y-a.y*b.x;
	}
	inline double slope(){
		return y/x;
	}
}p[N];
int stk[N],top;
ll f[N];
int a[N],n;
inline void trans(int i,int j){
	f[i]=f[j]+1ll*(i-j)*(i-j-1)/2+a[i];
}
inline bool check(int k,double s){
	return (p[stk[k]]-p[stk[k-1]]).slope()<2*s;
}
signed main(){
	freopen("lx.cpp","r",stdin);
	n=read();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=1;i<=n;i++){
		int l=1,r=top,res=0;
		while(l<=r){
			int mid=(l+r)>>1;
			if(check(mid,i))l=mid+1,res=mid;
			else r=mid-1;
		}
		trans(i,stk[res]);
		p[i].x=i,p[i].y=2ll*f[i]+1ll*i*i+i;
		while(top&&(p[stk[top]]-p[stk[top-1]])*(p[i]-p[stk[top-1]])<=0)top--;
		stk[++top]=i;
	}
	cout<<f[n];
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328771.html