• [SDOI2012]任务安排


    解析

    预算费用,和Luogu P2365 任务安排一样
    得到了同样的式子
    但是我们发现 (sumt_i) 可能小于零
    也就是说我们需要的斜率可能不再具有单调性
    所以我们要维护整个凸壳
    那么怎么找到最佳的决策点呢?
    其实就是 (slope(m,m-1) < sumt_i)(slope(m,m+1) >= sumt_i) 中的 (m)
    于是我们可以二分整个凸壳,找到这样的点
    也就是判断等价于 (slope(m , m + 1) >= sumt_i)
    满足这个不等式的决策可能成为最有决策,记录下来
    然后我们要找凸壳中更靠前的,于是 (r=mid-1)

    (Code)

    #include<cstdio>
    using namespace std;
    typedef long long LL;
    
    const int N = 3e5 + 5;
    int n , q[N];
    LL f[N] , T[N] , C[N] , s , t , c;
    
    double slope(int u , int v)
    {
    	if (C[u] == C[v]) return 1.0 / 0.0;
    	return 1.0 * ((f[u] - s * C[u]) - (f[v] - s * C[v])) / (1.0 * C[u] - C[v]);
    }
    
    int search(int l , int r , int m)
    {
    	if (l == r) return q[l];
    	int mid , res = r;
    	while (l <= r)
    	{
    		mid = (l + r) >> 1;
    		if (slope(q[mid] , q[mid + 1]) >= m) res = mid , r = mid - 1;
    		else l = mid + 1;
    	}
    	return q[res];
    }
    
    int main()
    {
    	scanf("%d%lld" , &n , &s);
    	for(register int i = 1; i <= n; i++)  
    		scanf("%lld%lld" , &t , &c) , T[i] = T[i - 1] + t , C[i] = C[i - 1] + c;
    	int r;
    	q[r = 1] = 0;
    	for(register int i = 1; i <= n; i++)
    	{
    		int j = search(1 , r , T[i]);
    		f[i] = f[j] + T[i] * (C[i] - C[j]) + s * (C[n] - C[j]);
    		while (r > 1 && slope(i , q[r]) < slope(q[r] , q[r - 1])) --r;
    		q[++r] = i;
    	}
    	printf("%lld" , f[n]);
    } 
    
  • 相关阅读:
    京东白条
    Linux命令(40)rm 命令
    Linux命令(39)rmdir 命令
    Linux命令(38)pstree命令
    Linux命令(37)type命令
    Linux命令(36)help命令
    Linux命令(35)du命令
    CentOS7修改主机名
    Linux命令(34)tac命令
    Linux命令(33)cat命令
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13680969.html
Copyright © 2020-2023  润新知