• 斜率优化——bzoj1010


    把hdu3507的式子转化一下就行

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define N 500005
    struct point{
        ll x,y;//x=sum[i],y=dp[i]+sum[i]*sum[i]
        point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
        point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
    };
    ll cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
    
    ll n,L,dp[N],a[N],sum[N],t[N];
    point q[N];
    int head,tail;
    void pop(ll k){//sum[i]显然递增,所以可以把前面斜率<=k的全部pop掉 
        while(tail>head && q[head+1].y-q[head].y<=k*(q[head+1].x-q[head].x))
            head++;
    }
    void push(point k1){//sum[i]递增,所以必定可以更新凸包
        while(tail>head && cross(q[tail]-k1,q[tail-1]-k1)>=0)tail--;
        q[++tail]=k1;
    }
    
    int main(){
        while(cin>>n>>L){
        memset(sum,0,sizeof sum);
        
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
        for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
        for(int i=1;i<=n;i++)t[i]=sum[i]+i;
        
        dp[0]=0;tail=head=1;
        q[tail]=((point){0,0});
        for(int i=1;i<=n;i++){
            pop(2*t[i]);//在凸包上找到该斜率对应的点
            dp[i]=t[i]*t[i]+(L+1)*(L+1)-2*t[i]*(L+1);
            dp[i]+=-2*t[i]*q[head].x+q[head].y;
            push((point){t[i],dp[i]+t[i]*t[i]+2*t[i]*(L+1)});//把第i个点更新到二维坐标轴上,更新凸包 
            //cout<<i<<" "<<dp[i]<<" "<<q[head].x<<" "<<q[head].y<<" "<<head<<" "<<tail<<endl;
        }
        cout<<dp[n]<<'
    ';
        }
    } 
  • 相关阅读:
    [置顶] 输入子系统
    多线程知识点总结
    mybatis知识点总结
    redis知识点及常见面试题
    spring知识点(面试题)
    【linux】vim常用命令
    Linux常用命令大全
    Java 位运算(移位、位与、或、异或、非)
    图论之堆优化的Prim
    BZOJ3261 最大异或和 解题报告(可持久化Trie树)
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12519246.html
Copyright © 2020-2023  润新知