CH301 任务安排2 题解报告
【题目大意】
题意同任务安排1,数据范围变为$1\le N\le3*10^5,1\le S,T_i,C_i\le512$
【思路分析】
我们对任务安排1的解法稍作优化
设$st,sc$分别为$T,C$数组的前缀和,转移方程转化为$f[i]=min\{f[j]-(st[i]+S)*sc[j]\}(0\le j<i)+st[i]*sc[i]+S*sc[n]$
我们去掉$min$函数,然后将关于$j$的值$f[j],sc[j]$看作变量,其余部分看作常量,则$f[j]=(st[i]+S)*sc[j]+f[i]-st[i]*sc[i]-S*sc[n]$
然后我们以$sc[j]$为横坐标,$f[j]$为纵坐标建立平面直角坐标系,那么这就是一条斜率为$st[i]+S$,在$y$轴上截距为$f[i]-st[i]*sc[i]-S*sc[n]$的直线。相当于,候选集合是坐标系中的一个点集,每个决策$j$都对应着坐标系中的一个点$(sc[j],f[j])$。直线的斜率是固定的,截距越小,则$f[i]$越小。
为了及时排除无用决策,我们维护一个“连接相邻两点的线段斜率单调递增”的“下凸壳”。对于一条斜率为$k$的直线,若某个顶点左侧线段斜率$<k$,右侧线段斜率$>k$,则该顶点即为最优决策。
具体地,我们可以利用单调队列来维护这个下凸壳。单调队列$q$中保存若干个决策变量,对应凸壳上的顶点,且满足横坐标递增,连接相邻两点的线段斜率也单调递增。
对于每个状态变量$i$,我们进行如下操作:
$1.$检查队头的两个决策变量$q[l],q[l+1]$,若斜率$\frac{f[q[l+1]]-f[q[l]]}{sc[q[l+1]]-sc[q[l]]}\le S+st[i]$,则把$q[l]$出队,重复该操作直到队头元素不满足条件为止
$2.$此时的队头$q[l]$即为最优决策,计算出$f[i]$
$3.$检查队尾元素$q[r-1],q[r]$和$i$是否满足斜率单调递增,若不满足则将$q[r]$出队,重复操作直到队尾元素满足斜率单调递增,将$i$插入进队尾
整个算法的时间复杂度为$O(N)$
【代码实现】
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #define g() getchar() 8 #define rg register 9 #define go(i,a,b) for(rg int i=a;i<=b;i++) 10 #define back(i,a,b) for(rg int i=a;i>=b;i--) 11 #define db double 12 #define ll long long 13 #define il inline 14 #define pf printf 15 #define mem(a,b) memset(a,b,sizeof(a)) 16 using namespace std; 17 int fr(){ 18 int w=0,q=1; 19 char ch=g(); 20 while(ch<'0'||ch>'9'){ 21 if(ch=='-') q=-1; 22 ch=g(); 23 } 24 while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g(); 25 return w*q; 26 } 27 const int N=3e5+2; 28 int n,s,q[N],l=1,r=1; 29 ll f[N],st[N],sc[N],as; 30 int main(){ 31 //freopen("","r",stdin); 32 //freopen("","w",stdout); 33 n=fr();s=fr(); 34 go(i,1,n)st[i]=st[i-1]+fr(),sc[i]=sc[i-1]+fr(); 35 mem(f,0x3f);f[0]=0; 36 q[1]=0;as=s*sc[n]; 37 go(i,1,n){ 38 rg ll k=s+st[i]; 39 while(l<r&&f[q[l+1]]-f[q[l]]<=k*(sc[q[l+1]]-sc[q[l]]))l++; 40 f[i]=f[q[l]]-k*sc[q[l]]+st[i]*sc[i]+as; 41 while(l<r&&(f[q[r]]-f[q[r-1]])*(sc[i]-sc[q[r]])>=(f[i]-f[q[r]])*(sc[q[r]]-sc[q[r-1]]))r--; 42 q[++r]=i; 43 } 44 pf("%lld\n",f[n]); 45 return 0; 46 }
原文地址:https://www.cnblogs.com/THWZF/p/11716740.html
- 从数据到代码——通过代码生成机制实现强类型编程[上篇]
- Spring读书笔记——bean加载
- Java8-初识Lambda
- 我的WCF之旅(5):面向服务架构(SOA)和面向对象编程(OOP)的结合——如何实现Service Contract的重载(Overloading)
- WCF技术剖析之三十:一个很有用的WCF调用编程技巧[下篇]
- 谈谈WCF中的Data Contract(3):WCF Data Contract对Collection & Dictionary的支持
- WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]
- 我的WCF之旅(4):WCF中的序列化[下篇]
- [WCF权限控制]模拟(Impersonation)与委托(Delegation)[上篇]
- Android EclipseIDE技巧
- 什么是编译错误,运行时错误及逻辑错误?
- 我的WCF之旅(4):WCF中的序列化[上篇]
- WCF技术剖析之二十八:自己动手获取元数据[附源代码下载]
- 微信年度重磅“小游戏”上线,罗胖一度退出的小程序正在逆袭
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- js原生模态登录框
- 客户决策 | 我的代码没有else
- LeetCode 1595 Minimum Cost to Connect Two Groups of Points (动态规划)
- js DOM系统
- css的radial-gradient大详解
- 你想知道的优惠券业务,SkrShop告诉你
- js汇率计算器系统
- 数学--数论--欧拉降幂和广义欧拉降幂(实用好理解)
- JS逐步教你做(自己版本)的视频播放器(我先声明,step我不懂是什么意思,所以没用)
- 【mysql系列】细谈“explain”之理论Part
- 如果用java swing编写一个五子棋(人人对战)
- 【mysql系列】细谈explain执行计划之“谜”
- 洛谷 P1352 没有上司的舞会(树形 DP)
- CF思维联系– CodeForces - 991C Candies(二分)
- 洛谷P1122 最大子树和 树形DP初步