动态开点李超线段树求助25pts

P4655 [CEOI2017] Building Bridges

黑影洞人 @ 2022-08-30 23:09:53

#include<cstdio>
#include<algorithm>
#define lc lson[p]
#define rc rson[p]
#define inf 2147483647
#define N 1919810
using namespace std;
int dp[N];
struct Li_Chao_Segement_Tree{
    int tot,cnt=1,k[N],b[N],s[N],lson[N],rson[N],rt=1;
    int y(int x,int id){return x*k[id]+b[id];}
    void update(int &p,int l,int r,int k){
        if(!p)p=++cnt;
        if(l==r){
            if(y(l,k)<y(l,s[p]))s[p]=k;
            return;
        }
        int mid=(l+r)/2;
        if(y(mid,k)<y(mid,s[p]))swap(k,s[p]);
        if(y(l,k)<y(l,s[p]))update(lc,l,mid,k);
        else if(y(r,k)<y(r,s[p]))update(rc,mid+1,r,k);
    }
    void insert(int ki,int bi){
        k[++tot]=ki,b[tot]=bi;
        update(rt,0,N,tot);
    }
    int get(int p,int l,int r,int x){
        if(!p)return inf;
        if(l==r&&l==x)return y(l,s[p]);
        int mid=(l+r)/2;
        return min(x<=mid?get(lc,l,mid,x):get(rc,mid+1,r,x),y(x,s[p]));
    }
}lic;
int n,h[N],s[N];
signed main(){
    scanf("%d",&n);lic.b[0]=inf;
    for(int i=1;i<=n;i++)scanf("%d",&h[i]);
    for(int i=1;i<=n;i++)scanf("%d",&s[i]),s[i]+=s[i-1];
    lic.insert(-2*h[1],h[1]*h[1]-s[1]);
    for(int i=2;i<=n;i++){
        dp[i]=h[i]*h[i]+s[i-1]+lic.get(lic.rt,0,N,h[i]);
        lic.insert(-2*h[i],dp[i]+h[i]*h[i]-s[i]);
    }
    printf("%d",dp[n]);
    return 0;
}

by 黑影洞人 @ 2022-08-30 23:10:54

十年OI一场空,不开__见祖宗

此贴完结


by 黑影洞人 @ 2022-08-30 23:11:31

@黑影洞人 调了半天才发现忘记开long long 了


|