• [学习笔记] 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

    传送门

  • 相关阅读:
    1082 射击比赛 (20 分)
    1091 N-自守数 (15 分)
    1064 朋友数 (20 分)
    1031 查验身份证 (15 分)
    1028 人口普查 (20 分)
    1059 C语言竞赛 (20 分)
    1083 是否存在相等的差 (20 分)
    1077 互评成绩计算 (20 分)
    792. 高精度减法
    791. 高精度加法
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/14908532.html
Copyright © 2020-2023  润新知