BZOJ2726[SDOI2012]任务安排 斜率优化+cdq分治
Posted CQzhangyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2726[SDOI2012]任务安排 斜率优化+cdq分治相关的知识,希望对你有一定的参考价值。
【BZOJ2726】[SDOI2012]任务安排
Description
机器上有N个需要处理的任务,它们构成了一个序列。这些任务被标号为1到N,因此序列的排列为1,2,3...N。这N个任务被分成若干批,每批包含相邻的若干任务。从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti。在每批任务开始前,机器需要启动时间S,而完成这批任务所需的时间是各个任务需要时间的总和。注意,同一批任务将在同一时刻完成。每个任务的费用是它的完成时刻乘以一个费用系数Fi。请确定一个分组方案,使得总费用最小。
Input
第一行两个整数,N,S。
接下来N行每行两个整数,Ti,Fi。
Output
一个整数,为所求的答案。
Sample Input
5 1
1 3
3 2
4 3
2 3
1 4
1 3
3 2
4 3
2 3
1 4
Sample Output
153
题解:用f[i]表示做完前i个任务的最小费用,但是做完当前任务的时间对后面的任务也会造成影响,所以我们提前应计算费用,不难列出方程:
设st表示T的前缀和,sf表示F的前缀和,所以有:
$f[i]=\min \{ f[j]+(st[i]-st[j]+S)*(sf[n]-sf[j])\}$
移个项显然就变成了斜率优化的形式。不过坑的地方是,T可能是负数,所以斜率不是单调的,所以用cdq分治即可。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=300010; typedef long long ll; typedef long double ld; int n; ll S; struct node { int x,org,k; ll y,f; }s[maxn],p[maxn]; int q[maxn]; inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘) f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+(gc^‘0‘),gc=getchar(); return ret*f; } bool cmpk(const node &a,const node &b) { return a.k>b.k; } bool cmpo(const node &a,const node &b) { return a.org<b.org; } inline ld slope(int a,int b) { if(s[a].x==s[b].x) return (s[b].y>=s[a].y)?(1e20):(-1e20); else return ld(s[b].y-s[a].y)/(s[b].x-s[a].x); } void solve(int l,int r) { if(l==r) { s[l].y=(ll)s[l].x*(s[l].k-S)-s[l].f; return ; } register int mid=(l+r)>>1,i,h1=l,h2=mid+1; for(i=l;i<=r;i++) { if(s[i].org<=mid) p[h1++]=s[i]; else p[h2++]=s[i]; } for(i=l;i<=r;i++) s[i]=p[i]; solve(l,mid); register int h=1,t=0; for(i=l;i<=mid;i++) { while(h<t&&slope(q[t],i)>=slope(q[t-1],q[t])) t--; q[++t]=i; } for(i=mid+1;i<=r;i++) { while(h<t&&slope(q[h],q[h+1])>=s[i].k) h++; s[i].f=min(s[i].f,s[q[h]].f+s[q[h]].x*(s[i].k-s[q[h]].k+S)); } solve(mid+1,r); h1=l,h2=mid+1; for(i=l;i<=r;i++) { if(h1<=mid&&(h2>r||s[h1].x<s[h2].x)) p[i]=s[h1++]; else p[i]=s[h2++]; } for(i=l;i<=r;i++) s[i]=p[i]; } int main() { n=rd(),S=rd(); int i; for(i=1;i<=n;i++) s[i].k=s[i-1].k+rd(),s[i-1].x=rd(),s[i].org=i; for(i=n-1;i>=0;i--) s[i].x+=s[i+1].x; for(i=1;i<=n;i++) s[i].f=s[0].x*(s[i].k+S); sort(s+1,s+n+1,cmpk); solve(1,n); sort(s+1,s+n+1,cmpo); printf("%lld",s[n].f); return 0; }
以上是关于BZOJ2726[SDOI2012]任务安排 斜率优化+cdq分治的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 2726 [SDOI2012]任务安排(斜率DP+CDQ分治)
BZOJ2726 [SDOI2012]任务安排 斜率优化 + cdq分治
bzoj 2726: [SDOI2012]任务安排cdq+斜率优化