任务安排4情况1题解(?)

前排提示

  • 本题来源于李煜东dalao的《算法竞赛进阶指南》0x5A斜率优化中的思考题:任务安排4的第一种情况,其实是太蒻了不会写都为负的情况,即\(T_i>0\) && \(C_i\)可能有\(C_i<0\),转移方程及代码实现基本按照蓝书配套讲解实现,仅给出粗略的转移方程等和代码实现,不懂之处请参考讲解视频

题目描述

机器上有 \(n\) 个需要处理的任务,它们构成了一个序列。这些任务被标号为 \(1\)\(n\),因此序列的排列为 \(1 , 2 , 3 \cdots n\)。这 \(n\) 个任务被分成若干批,每批包含相邻的若干任务。从时刻 \(0\) 开始,这些任务被分批加工,第 \(i\) 个任务单独完成所需的时间是 \(T_i\)。在每批任务开始前,机器需要启动时间 \(s\),而完成这批任务所需的时间是各个任务需要时间的总和。

注意,同一批任务将在同一时刻完成。每个任务的费用是它的完成时刻乘以一个费用系数 \(C_i\)

请确定一个分组方案,使得总费用最小。

输入格式

第一行一个整数 \(n\)。第二行一个整数 \(s\)

接下来 \(n\) 行,每行有一对整数,分别为 \(T_i\)\(C_i\),表示第 \(i\) 个任务单独完成所需的时间是 \(T_i\) 及其费用系数 \(C_i\)

输出格式

一行,一个整数,表示最小的总费用。

输入输出样例 #1

输入 #1

5
1
1 3
3 2
4 3
2 3
1 4

输出 #1

153

说明/提示

对于 \(100\%\) 数据,\(1 \le n \le 3 \times 10^5\)\(1 \le s \le 2^8\)\(1\le T_i \le 2^8\)\(-2^8 \le C_i \le 2^8\)

solve

  • 手写的转移方程可能有错哦
  • ht表示t的后缀hc表示c的后缀
  • 转移方程:
    • 初始(省去min):\(f_i=f_j+(ht_1-ht_j)*(hc_i-hc_j)+s*hc_i\)
    • 整理出的函数:\(f_j+ht_j*hc_j-ht_1*hc_j=hc_i*ht_j+f_i-(ht_1+s)*hc_i\)
      • 其中:\(y=f_j+ht_j*hc_j-ht_1*hc_j\)\(k=hc_i\)\(x=ht_j\)\(b=f_i-(ht_1+s)*hc_i\)

分步实现

  • 初始化
void init()
{
	for (int i=n;i>=1;i--)
	{
		ht[i]=t[i]+ht[i+1];
		hc[i]=c[i]+hc[i+1];
	}
}
memset(f,0x3f,sizeof(f));
init();
f[n+1]=0;
l++;
q[++r]=n+1;
  • 求y
long long get(int j) {return f[j]+ht[j]*hc[j]-ht[1]*hc[j];}
  • 二分
long long binary(int i,int k)
{
	if (l == r) return q[l];
	int L=l,R=r;
	while (L<R)
	{
		int mid=(L+R) >> 1;/*和移位*/
		if (get(q[mid+1])-get(q[mid])<=k*(ht[q[mid+1]]-ht[q[mid]])) L=mid+1;
		else R=mid;
	}
	return q[L];
}
  • 转移
f[i]=f[p]+(ht[1]-ht[p])*(hc[i]-hc[p])+s*hc[i];
  • 维护单调性
while (l<r && (get(q[r])-get(q[r-1]))*(ht[i]-ht[q[r]])>=(get(i)-get(q[r]))*(ht[q[r]]-ht[q[r-1]])) r--;

Code

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
constexpr int maxn=3e5+10;
int n,s;
long long t[maxn],c[maxn];
long long ht[maxn],hc[maxn];
long long f[maxn];
long long q[maxn],l,r;
long long get(int j) {return f[j]+ht[j]*hc[j]-ht[1]*hc[j];}
long long binary(int i,int k)
{
	if (l == r) return q[l];
	int L=l,R=r;
	while (L<R)
	{
		int mid=(L+R) >> 1;/*和移位*/
		if (get(q[mid+1])-get(q[mid])<=k*(ht[q[mid+1]]-ht[q[mid]])) L=mid+1;
		else R=mid;
	}
	return q[L];
}
void init()
{
	for (int i=n;i>=1;i--)
	{
		ht[i]=t[i]+ht[i+1];
		hc[i]=c[i]+hc[i+1];
	}
}
int main()
{
	memset(f,0x3f,sizeof(f));
	cin >> n >> s;
	for (long long i=1;i<=n;i++) cin >> t[i] >> c[i];
	init();
	f[n+1]=0;
	l++;
	q[++r]=n+1;
	for (long long i=n;i>=1;i--)
	{
		long long p=binary(i,hc[i]);
		f[i]=f[p]+(ht[1]-ht[p])*(hc[i]-hc[p])+s*hc[i];
		while (l<r && (get(q[r])-get(q[r-1]))*(ht[i]-ht[q[r]])>=(get(i)-get(q[r]))*(ht[q[r]]-ht[q[r-1]])) r--;
		q[++r]=i;
	}
	cout << f[1] << endl;
	return 0;
}

鸣谢

  • 李煜东dalao
  • wang7979
posted @ 2026-05-27 14:11  msjing  阅读(11)  评论(0)    收藏  举报