任务安排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

浙公网安备 33010602011771号