[AcWing303]任务安排2

有 \(N\) 个任务排成一个序列在一台机器上等待执行,它们的顺序不得改变。机器会把这 \(N\) 个任务分成若干批,每一批包含连续的若干个任务。从时刻 \(0\) 开始,任务被分批加工,执行第 \(i\) 个任务所需的时间是 \(t[i]\) 。另外,在每批任务开始前,机器需要 \(S\) 的启动时间,故执行一批任务所需的时间是启动时间 \(S\) 加上每个任务所需时间之和。一个任务执行后,将在机器中稍作等待,直至该批任务全部执行完毕。也就是说,同一批任务将在同一时刻完成。每个任务的费用是它的完成时刻乘以一个费用系数 \(c[i]\) 。请为机器规划一个分组方案,使得总费用最小。

\(1≤N≤3∗10^5\)

\(1≤S,Ti,Ci≤512\)

设 \(T[i]\) 为时间的前缀和 , \(C[i]\) 是系数 \(c\) 的前缀和 . 在一批任务开始对后续任务产生影响时,就先把费用累加到答案中. 这就是"费用提前计算"的思想 .

对于每一次转移, 有 \(chkmin(f[i], f[j] + (C[j] - C[i]) * T[i] + S * (C[n] - C[j]))\)

考虑到数据范围很像斜率优化 , 把式子转化为斜率优化的形式 :

\(f[j] = (S + T[i]) * C[j] - S * C[n] - T[i] * C[i] + f[i]\)

发现斜率是固定的 , 当截距最小时 \(f[i]\) 最小 . 所以要维护 \((C[j],f[j])\) 围成的下凸包 .

由于 \(f[j]\) 随 \(C[j]\) 单调递增 , \((S+T[i])\) 也是单调递增的 , 所以可以用单调队列维护 : 只保留两点间斜率 \(>=S+T[i]\) 的点 , 入队时检查有没有斜率递增

时间复杂度 \(O(n)\)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define Debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
register LL x=0,f=1;register char c=getchar();
while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
return f*x;
} const int N = 3e5 + 5; int T[N], C[N], q[N], f[N];
int n, S; int main(){
n = read(), S = read();
for(int i = 1; i <= n; ++i){
T[i] = T[i-1] + read();
C[i] = C[i-1] + read();
}
int l = 1, r = 1;
q[1] = 0; // 把0入队是因为j取0是合法的.
for(int i = 1; i <= n; ++i){
while(l < r && ((f[q[l+1]] - f[q[l]]) <= (S + T[i]) * (C[q[l+1]] - C[q[l]]))) l++;
f[i] = f[q[l]] - (T[i] + S) * C[q[l]] + C[i] * T[i] + S * C[n];
while(l < r && ((f[q[r]] - f[q[r-1]]) * (C[q[i]] - C[q[r]]) >= (f[q[i]] - f[q[r]]) * (C[q[r]] - C[q[r-1]]))) r--;
q[++r] = i;
}
printf("%d\n", f[n]);
}

[AcWing304]任务安排3

\(1≤N≤3∗10^5 ; 0≤S,c[i]≤512 ; -512≤t[i]≤512\)

完成的时间可以为负数 , 则 \(S+T[i]\) 不再具有单调性 . 所以在单调队列中二分查找出对应的位置 , 不需要出队 , 但需要维护入队时的斜率单调性

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define Debug(x) cout<<#x<<"="<<x<<endl
#define int long long
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
register LL x=0,f=1;register char c=getchar();
while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
return f*x;
} const int N = 3e5 + 5; int f[N], q[N], T[N], C[N];
int n, S; inline int find(int L, int R, int x){
while(L < R){
int mid = (L + R) >> 1;
if((f[q[mid+1]] - f[q[mid]]) <= x * (C[q[mid+1]] - C[q[mid]])) L = mid + 1; ///
else R = mid;
}
return L;
} signed main(){
n = read(), S = read();
for(int i = 1; i <= n; ++i){
T[i] = T[i-1] + read();
C[i] = C[i-1] + read();
}
int l = 1, r = 1;
for(int i = 1; i <= n; ++i){
int p = find(l, r, S + T[i]);
f[i] = f[q[p]] - (S + T[i]) * C[q[p]] + S * C[n] + T[i] * C[i];
while(l < r && ((f[q[r]] - f[q[r-1]]) * (C[i] - C[q[r]]) >= (f[i] - f[q[r]]) * (C[q[r]] - C[q[r-1]]))) r--;
q[++r] = i;
}
printf("%lld\n", f[n]);
}

最新文章

  1. 细说gulp
  2. 【转】android 属性动画之 ObjectAnimator
  3. Maven 实用命令和技巧
  4. POJ 2352
  5. PHP5中使用PDO连接数据库的方法
  6. ASP.NET 程序中删除文件夹导致session失效解决问题
  7. 关于linux curl 地址参数的问题
  8. java 24点算法实现
  9. 关于java对象的思考
  10. ☀【组件】字符串 string
  11. 【转】java中静态代码块的用法 static用法详解
  12. Check Mysql Database Size
  13. 用overflow-y 解决web页面抖动问题
  14. Libcurl最初的实现tfp上传和下载功能
  15. 基于webpack的React项目搭建(一)
  16. python 使用多进程打开多个cmd窗口,并在子进程结束之后关闭cmd窗口
  17. bash小技巧1 获取文件当前路径
  18. mybatis-spring-1.2.2.jar下载地址
  19. 关于win10安装javaJDK时遇到的问题
  20. A - 小孩报数问题

热门文章

  1. Centos创建用户并授权
  2. 剧终—AFO.
  3. Centos 7 搭建蓝鲸V4.1.16稳定社区版
  4. 虚拟视点demo
  5. [python之ipython] jupyter notebook在云端服务器上开启,本地访问
  6. #define定义宏函数 的正确使用
  7. Linux 网络通信命令之 netstat
  8. 同源策略和Ajax跨域访问
  9. 1.springAOP原理分析
  10. 3.ibatis4种事务类型浅析