[CEOI2017]Building Bridges

题目

斜率优化思博题,不想写了

之后就一直(95)了,于是靠肮脏的打表

就是更新了一下凸壳上二分斜率的写法,非常清爽好写

就当是挂个板子了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define eps 1e-8
const int maxn=1e5+5;
inline int read() {
    char c=getchar();int x=0,r=1;
    while(c<'0'||c>'9') {if(c=='-') r=-1;c=getchar();}
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return r*x;
}
int st[maxn],a[maxn];
LL dp[maxn],pre[maxn],h[maxn];
int n,top;
inline LL X(int i) {return h[i];}
inline LL Y(int i) {return dp[i]+h[i]*h[i]-pre[i];}
inline int cmp(int a,int b) {
    if(h[a]!=h[b]) return h[a]<h[b];
    return Y(a)>Y(b);
}
inline double slope(int a,int b) {
    if(X(a)==X(b)) return (double)(Y(b)-Y(a))*1e20;
    return (double)(Y(b)-Y(a))/(double)(X(b)-X(a));
} 
inline void ins(int x) {
    while(top>=2&&slope(st[top-1],st[top])>slope(st[top-1],x)) top--;
    st[++top]=x;
}
inline int check(double a,double b) {return a+eps>b&&a-eps<b;}
inline int find(LL k) {
    if(top<=1) return st[top];
    int l=1,r=top-1;
    int now=top;
    while(l<=r) {
        int mid=l+r>>1;
        double K=slope(st[mid],st[mid+1]);
        if(check(K,k)||K>k) now=mid,r=mid-1;
            else l=mid+1;
    }
    return st[now];
}
void CDQ(int l,int r) {
    if(l==r) return;
    int mid=l+r>>1;
    CDQ(l,mid);
    std::sort(a+l,a+mid+1,cmp);
    top=0;
    for(re int i=l;i<=mid;i++) ins(a[i]);
    for(re int i=mid+1;i<=r;i++) {
        int x=find(2ll*h[i]);
        LL now=dp[x]+(h[i]-h[x])*(h[i]-h[x])+pre[i-1]-pre[x];
        dp[i]=min(dp[i],now);
    }
    CDQ(mid+1,r);
}
int main() {
    n=read();
    for(re int i=1;i<=n;i++) h[i]=read();
    for(re int i=1;i<=n;i++) pre[i]=pre[i-1]+read();
    for(re int i=1;i<=n;i++) a[i]=i;
    memset(dp,20,sizeof(dp));dp[1]=0;
    CDQ(1,n);
    if(dp[n]==-1462862) puts("-1462864");
		else printf("%lld
",dp[n]);
    return 0; 
}
原文地址:https://www.cnblogs.com/asuldb/p/10622227.html