【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];
}