【bzoj2726】[SDOI2012]任务安排

来源:互联网 发布:淘宝优惠券搜索软件 编辑:程序博客网 时间:2024/05/21 20:04

首先暴力dp应该是很简单的

dp[i]=min(dp[j]+cost[i]*(T[i]-T[j]+S)) (j>i)

本来简单的斜率优化因为脑洞大的出题人一句时间可以是负的变成了cdq维护dp

但比较好的一点是可以先把所有决策点加入凸包,在枚举询问(按斜率排序(T[pos]))在凸包上跑答案。

#include <bits/stdc++.h>#define gc getchar()#define N 500009#define mid (l+r>>1)#define ll long longusing namespace std;const ll inf=0x3f3f3f3f3f3f3f3f;ll n,s,t[N],f[N],T[N],F[N],dp[N],top;//X(i)=F[i],Y(i)=dp[j]-F[n]*T[j]+F[j]*T[j]-s*F[j],a(i)=T[i]//dp[i]=min{X(i)*-a(i)+Y(i)}//Y(i)=a(i)*X(i)+pstruct node{ll k,x,y,pos,pd;node(ll pos=0):pos(pos){k=T[pos];}void get(){x=F[pos],y=dp[pos]-F[n]*T[pos]+F[pos]*T[pos]-s*F[pos];}bool operator <(const node &rhs) const{return k<rhs.k;}}q[N],now[N],sta[N];bool cmp(const node &lhs,const node &rhs){return lhs.x<rhs.x||(lhs.x==rhs.x&&lhs.y<rhs.y);}ll read(){ll x=1;char ch;while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;ll s=ch-'0';while (ch=gc,ch<='9'&&ch>='0') s=s*10+ch-'0';return s*x;}ll up(const node &a,const node &b){return a.y-b.y;}ll down(const node &a,const node &b){return a.x-b.x;}void solve(ll l,ll r){if (l==r){q[l].get();return;}ll l1=l,l2=mid+1;for (ll i=l;i<=r;i++)if (q[i].pos<=mid) now[l1++]=q[i];else now[l2++]=q[i];for (ll i=l;i<=r;i++) q[i]=now[i];solve(l,mid);top=0;for (ll i=l;i<=mid;i++)//k is increasing {while (top>=2&&up(q[i],sta[top])*down(sta[top],sta[top-1])<up(sta[top],sta[top-1])*down(q[i],sta[top])) top--;sta[++top]=q[i];}ll j=1;for (ll i=mid+1;i<=r;i++){while (j<top&&q[i].k*down(sta[j],sta[j+1])<up(sta[j],sta[j+1])) j++;dp[q[i].pos]=min(dp[q[i].pos],sta[j].y-sta[j].x*q[i].k+F[n]*(T[q[i].pos]+s));}solve(mid+1,r);l1=l,l2=mid+1;for (ll i=l;i<=r;i++)if ((cmp(q[l1],q[l2])||(l2>r))&&l1<=mid) now[i]=q[l1++];else now[i]=q[l2++];for (ll i=l;i<=r;i++) q[i]=now[i];}int main(){n=read(),s=read();for (ll i=1;i<=n;i++)t[i]=read(),f[i]=read(),dp[i]=inf;for (ll i=1;i<=n;i++)T[i]=T[i-1]+t[i],F[i]=F[i-1]+f[i];for (ll i=0;i<=n;i++) q[i]=node(i);sort(q,q+n+1);solve(0,n);printf("%lld\n",dp[n]);return 0;}



原创粉丝点击