zoukankan      html  css  js  c++  java
  • 斜率优化

    感谢全机房唯一女装大佬 little-uu 的讲解

    对于斜率优化,妙极秒极,所以我是没办法讲 /摊手

    对于类似于 (f[i] = f[j] + a[i] imes b[j] + dots) 之类的式子可以使用斜率优化

    首先想办法将式子里的变量的下表全变成 i 或 j ,然后将 (a[i] imes b[j]) 形式的式子放到一边,只和 i 有关的式子也放到这一边,只跟 j 有关的式子放到另一边。

    我们得到类似于 (a[i] imes b[j] + f[i] + dots = f[j] + dots) 的式子。

    我们考虑一次函数 (y = kx + b)

    将其中 (a[i]) 视为 (k) ,(b[j]) 视为 (x) , (f[i] + dots) 视为 (b) , (f[j] + dots) 视为 (y)

    我们可以得到对于此直线,它经过 (left(b[j],f[j]+dots ight)) ,斜率为 (a[i]) ,(f[i]) 只跟截距有关。

    对于已经处理好的 (f[j]) 来说,都可以确定一个点,而对于需要计算的 (f[i]) 来说,都可以确定这条直线的斜率,两者结合可以求出一次函数截距。于是我们可以将问题转化。

    我们现在有一些点,需要 求出在特定斜率下的截距最值,可以知道可以对答案造成贡献的只能是凸包上的点,使用栈来维护凸包。对于 (a[i]) 单调增的题目来说,可以使用双端队列来进行均摊 (O(1)) 的转移,否则需要在凸包上二分。

    例题:P2120 [ZJOI2007]仓库建设

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    #define j1 q[l]
    #define j2 q[l+1]
    #define int long long
    
    using namespace std;
    
    int read()
    {
    	int a = 0,x = 1;char ch = getchar();
    	while(ch > '9' || ch < '0') {if(ch == '-') x = -1;ch = getchar();}
    	while(ch >= '0' && ch <= '9') {a = a*10 + ch-'0';ch = getchar();}
    	return a*x;
    }
    const int N=1e6+7;
    int n,x[N],p[N],c[N];
    int a[N],b[N],A[N],f[N];
    int q[N],l=1,r=1;
    
    inline bool check(int a1,int a2,int a3)
    {
    	return (b[a3]+f[a3]-b[a1]-f[a1])*(a[a3]-a[a2]) > (b[a3]+f[a3]-b[a2]-f[a2])*(a[a3]-a[a1]);
    }
    
    signed main()
    {
    	n = read();
    	for(int i = 1;i <= n;i ++) {
    		x[i] = read(),p[i] = read(),c[i] = read();
    		a[i] = a[i-1]+p[i],b[i] = b[i-1]+x[i]*p[i];
    		A[i] = x[i]*a[i];
    	}
    	for(int i = 1;i <= n;i ++) {
    		while(l<r) {
    			if((b[j1]+f[j1] - b[j2]-f[j2]) > x[i]*(a[j1]-a[j2])) l ++;
    			else break;
    		}
    		#define j q[l]
    		f[i] = f[j]+A[i]-x[i]*a[j]-b[i]+b[j]+c[i];
    		while(l<r) {
    			if(check(q[r-1],q[r],i)) r --;
    			else break;
    		}
    		q[++r] = i;
    	}
    	printf("%lld",f[n]);
    	return 0;
    }
    
  • 相关阅读:
    升级CentOS内核
    npm、component、spm、bower的区别
    Bower的使用
    Mac安装Bower
    Bower是什么?
    Mac下安装与配置Go语言开发环境
    jenkins升级为2.134
    nexus实现从windows迁移至Linux平台
    Jenkins构建完成后实现自动将war包部署到指定服务器
    使用jenkins构建一个maven项目
  • 原文地址:https://www.cnblogs.com/nao-nao/p/13999080.html
Copyright © 2011-2022 走看看