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

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;
}

 

posted @ 2017-03-10 15:41  Cjk_2001  阅读(328)  评论(1编辑  收藏  举报