[SDOI2012]任务安排

XII.[SDOI2012]任务安排

同上一题一样,不过,这题的ti可能有负数,这就意味着前缀和不再是单调增的!

我们不能再像前一题一样用单调队列维护了——但是因为队尾的单调性仍然存在,我们仍然可以维护上凸包。这就启发我们使用单调栈来维护斜率,并且在单调栈中二分。

我们不妨想一想,如果这个c也有可能是负数怎么办?

c是负数就意味着不再具有一个明确的凸壳——我们在两边同除时不知道c[j]c[k]是正是负。因此,我们可以采用平衡树来支持插入斜率和查询,复杂度O(nlogn)。(该方法纯属口胡,请勿当真)

本题代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,t[300100],c[300100],f[300100],s[300100],tp;
signed main(){
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++)scanf("%lld%lld",&t[i],&c[i]),t[i]+=t[i-1],c[i]+=c[i-1];
	for(int i=1;i<=n;i++){
		int L=0,R=tp;
		while(L<R){
			int mid=(L+R)>>1;
			if((f[s[mid]]-f[s[mid+1]])>=(c[s[mid]]-c[s[mid+1]])*(m+t[i]))L=mid+1;
			else R=mid;
		}
		f[i]=f[s[L]]+m*(c[n]-c[s[L]])+t[i]*(c[i]-c[s[L]]);
		while(tp&&(f[s[tp-1]]-f[s[tp]])*(c[s[tp]]-c[i])>=(f[s[tp]]-f[i])*(c[s[tp-1]]-c[s[tp]]))tp--;
		s[++tp]=i;
	}
	printf("%lld\n",f[n]);
	return 0;
}

posted @   Troverld  阅读(46)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示