zoukankan      html  css  js  c++  java
  • 任务安排 3

    https://loj.ac/problem/10186

    题目描述

      同任务安排2,不过(T)可能为负。

    思路

      由于(T)为负,我们就无法保证前缀和的单调性,所以我们不能直接贪心的进行选择,而是要维护整个凸壳,不过我们仍然有类似的结论,对于一个点,如果它左边的线段斜率小于(k),右边的大于(k),那么它一定是最优的,所以我们可以在凸壳的单调队列中二分查找这个值。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll N=3e5+10;
    ll f[N],sumt[N],sumc[N],q[N];
    
    ll read()
    {
    	ll res=0,w=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    	return res*w;
    }
    
    ll search(ll r,ll k)
    {
    	ll l=0,ans=0;
    	while(l<=r)
    	{
    		ll mid=l+r>>1;
    		if((f[q[mid+1]]-f[q[mid]])>k*(sumc[q[mid+1]]-sumc[q[mid]]))ans=mid,r=mid-1;
    		else l=mid+1;
    	}
    	return q[ans];
    }
    int main()
    {
    	ll n=read(),s=read();
    	for(ll i=1;i<=n;i++)
    		sumt[i]=sumt[i-1]+read(),
    		sumc[i]=sumc[i-1]+read();
    	ll l=0,r=0;
    	for(ll i=1;i<=n;i++)
    	{
    		ll j=search(r,s+sumt[i]);
    		f[i]=f[j]-(s+sumt[i])*sumc[j]+sumt[i]*sumc[i]+s*sumc[n];
    		while(l<r&&(f[q[r]]-f[q[r-1]])*(sumc[i]-sumc[q[r]])>=(f[i]-f[q[r]])*(sumc[q[r]]-sumc[q[r-1]]))
    			r--;
    		q[++r]=i;
    //		cout<<'x'<<j<<' '<<f[i]<<endl;
    	}
    	printf("%lld
    ",f[n]);
    }
    
    
  • 相关阅读:
    用户管理
    网线制作与分类
    5.虚函数,覆盖,多态,异常处理
    4.类的继承
    3.运算符重载
    7.STL
    6.泛型编程与模板
    C++中>>,<<的重载问题
    2.名字空间和构造函数
    1.C和C++的区别
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11853083.html
Copyright © 2011-2022 走看看