zoukankan      html  css  js  c++  java
  • [学习笔记] Slope trick 折线算法

    前言

    这个东西 slope trick on codeforces 已经讲得很清楚了,我把他翻译成中文版,这能叫引进算法吗?

    好像没有听说过它的中文名,我就叫他折线算法吧。

    原理

    折线算法是描述函数的一种方式,我称适用于折线算法的函数为折线函数,折线函数通常满足下列性质:

    • 它是连续的。
    • 它可以被分成若干个直线函数,有其固定的斜率。
    • 它具有凸凹性,也就是每个直线函数斜率单增或单减。

    举个栗子:(f(x)=|x|) 就是最常见的折线函数。

    定义转折点为折线函数斜率突变的点的横坐标,绝对值函数转折点就是 (0)

    根据上述可以得出表示表示折线函数的方式,可重集 (S) 里的元素表示转折点,并且转折点出现一次代表折线函数斜率突变 (1),再加上最后一段的直线函数方程即可,绝对值函数可以表示成:([y=x,S={0,0}])

    折线函数有一个最重要的性质:可合并性( t mergable)),如果 (f(x))(g(x)) 是具有相同凸凹性的两个折线函数,那么合并之后的 (h(x)) 满足 (S_h=S_fcup S_g),最后一段的直线函数重新计算一下即可。

    原理讲完了,可以来做题了(( t zy):一节课讲课十分钟,做题三十分钟)

    例1

    题目描述

    点此看题

    解法

    把严格递增变成不严格递增要好做一些,执行 a[i]-=i 的操作即可。

    然后设计出暴力 (dp),设 (dp[i][x]) 表示让前 (i) 个元素递增,第 (i) 个元素是 (leq x) 的最小操作数。

    用折线算法维护这东西,设 (f_i(x)=dp[i][x]),首先要证明 (f_i) 是折线函数,定义辅助函数 (g_i(x)) 表示 (a_i=x) 时的最小操作数,不难发现 (f_i) 其实就是 (g_i) 的前缀最小值。

    可以考虑归纳证明,(f_0) 是折线函数,假设 (f_{i-1}) 是折线函数,那么 (g_i=f_{i-1}+|x-a_i|),所以 (g_i) 也是折线函数,因为 (f_i)(g_i) 的前缀最小值,等价于把后面斜率 (>0) 的一段变平,所以 (f_i) 也是折线函数。

    算法就蕴含在证明中,每次直接合并一个绝对值函数上来,然后更新最低点的函数值,最后把斜率为 (1) 的那一段掐掉即可,因为合并前斜率最大是 (0) 所以合并后最大是 (1),时间复杂度 (O(nlog n))

    总结

    折线算法需要单点函数值的合并,所以设计暴力状态的时候需要注意一下。

    证明折线函数可以使用归纳法,还可以定义辅助函数,主要利用的就是 ( t mergable) 的性质。

    #include <cstdio>
    #include <queue>
    using namespace std;
    #define int long long
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,ans;priority_queue<int> q;
    int Abs(int x)
    {
    	return x>0?x:-x;
    }
    signed main()
    {
    	n=read();
    	q.push(-2e9);
    	for(int i=1;i<=n;i++)
    	{
    		int x=read()-i;
    		q.push(x);q.push(x);
    		ans+=q.top()-x;
    		q.pop();
    	}
    	printf("%lld
    ",ans);
    }
    

    例2

    传送门

  • 相关阅读:
    条件注释,判断浏览器版本
    IE 兼容模式下不支持DIV CSS样式display:inline-block,解决
    Hibernate配置问题
    初学Hibernate
    Ognl基本使用
    初学Struts2-自定义拦截器及其配置
    初学structs2,表单验证简单补充
    初学structs2,表单验证
    structs2标签简单实用,及自定义转换器示例代码
    一些专业术语的总结
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/14908532.html
Copyright © 2011-2022 走看看