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
正解:cdq分治+斜率优化
解题报告:大体同上一篇cash的题解相同,但是有一个特别奇妙的地方(网络流好题 修车),
对于每一次分组,我们不是通过前面分了多少组来算它的费用,而是把在这里分组而对后面产生
的影响记在自己身上(因为在这里分一组之后,后面的每一组的时间都要加s+∑t),
所以我们能得出转移方程:dp[i]=min{dp[j]+s*(f[n]-f[j])+t[i]*(f[i]-f[j])}(t数组记得
是时间的前缀和,f数组记得是费用的前缀和);然后再把它拆开:dp[j]+s*f[n]-s*f[j]+t[i]*f[i]-t[i]*f[j]
s乘f[n]是一个定值,t[i]*f[i]只跟i有关,我们把它们视为常数,然后式子变成dp[j]+s*f[j]-t[i]*f[j];
dp[j]+s*f[j]只跟j有关,视为b,t[i]当为x,f[j]当为k,然后就成为了kx+b的形式,再套上cdq维护
x与k的单调性就可以用斜率优化了,时间复杂度O(nlogn)。
#include <iostream> #include <iomanip> #include <cstdlib> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #define RG register #define int long long #define ld long double #define File(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout) const int N = 400000; using namespace std; int gi(){ char ch=getchar();int x=0,q=0; while(ch<'0' || ch>'9') {if (ch=='-') q=1;ch=getchar();} while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return q? (-x) : x; } int n,s; int t[N],f[N],dp[N]; struct date{ double k,x,b;int t; bool operator < (const date &a) const{ return x<a.x; } }g[N],st[N],p[N]; inline void cdq(int l,int r){ if (l==r) return; int mid=(l+r)>>1,p1=l,p2=mid+1,head=1,tail=0; for (RG int i=l; i<=r; ++i) if (g[i].t<=mid) p[p1++]=g[i]; else p[p2++]=g[i]; for (RG int i=l; i<=r; ++i) g[i]=p[i]; cdq(l,mid); for (RG int i=l; i<=mid; ++i){ while(head<tail && (ld)(st[tail-1].b-st[tail].b)*(g[i].k-st[tail-1].k)>=(ld)(st[tail-1].b-g[i].b)*(st[tail].k-st[tail-1].k)) --tail; st[++tail]=g[i]; } sort(g+mid+1,g+r+1); for (RG int i=mid+1; i<=r; ++i){ while(head<tail && st[head].k*g[i].x+st[head].b>=st[head+1].k*g[i].x+st[head+1].b) ++head; dp[g[i].t]=min((double)dp[g[i].t],st[head].k*g[i].x+f[n]*s+st[head].b+t[g[i].t]*f[g[i].t]); g[i].b=dp[g[i].t]-s*f[g[i].t]; } cdq(mid+1,r);p1=l,p2=mid+1; for (RG int i=l; i<=r; ++i) if (p2>r || (p1<=mid && g[p1].k>=g[p2].k)) p[i]=g[p1++]; else p[i]=g[p2++]; for (RG int i=l; i<=r; ++i) g[i]=p[i]; return; } main(){ File("work"); n=gi(),s=gi(); for (RG int i=1; i<=n; ++i) t[i]=gi()+t[i-1],f[i]=gi()+f[i-1]; for (RG int i=1; i<=n; ++i){ dp[i]=s*f[n]+t[i]*f[i]; g[i]=(date){-f[i],t[i],dp[i]-s*f[i],i}; } cdq(1,n); printf("%lld",dp[n]); return 0; }