2018.09.05 bzoj2726: [SDOI2012]任务安排(斜率优化dp+二分)

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/82432631

传送门
T i 为正数的时候差不多。
只是这个时候 t i m e 数组没有了单调性,因此不能丢弃队头的元素,我们需要维护完整的下凸壳然后在上面二分。
写的时候如果用 s l o p e 函数算斜率好像会爆掉几个点,精度真神奇。。。
代码:

#include<bits/stdc++.h>
#define ll long long
#define N 300005
using namespace std;
inline ll read(){
    ll ans=0,w=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans*w; 
}
int n,hd,tl,q[N];
ll S,tim[N],w[N],f[N];
inline double slope(int x,int y){return 1.0*(f[x]-f[y])/(1.0*(w[x]-w[y]));}
inline int find(ll cmp){
    if(hd==tl)return q[hd];
    int l=hd,r=tl;
    while(l<r){
        int mid=l+r>>1;
        if(f[q[mid+1]]-f[q[mid]]<=cmp*(w[q[mid+1]]-w[q[mid]]))l=mid+1;
        else r=mid;
    }
    return q[l];
}
int main(){
    n=read(),S=read(),hd=1,tl=1;
    for(int i=1;i<=n;++i)tim[i]=read()+tim[i-1],w[i]=read()+w[i-1];
    for(int i=1;i<=n;++i){
        int pos=find(S+tim[i]);
        f[i]=f[pos]+S*(w[n]-w[pos])+tim[i]*(w[i]-w[pos]);
        while(hd<tl&&(f[q[tl]]-f[q[tl-1]])*(w[i]-w[q[tl]])>=(f[i]-f[q[tl]])*(w[q[tl]]-w[q[tl-1]]))--tl;
        q[++tl]=i;
    }
    cout<<f[n];
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/82432631
今日推荐