首页 > 其他分享 >slope trick

slope trick

时间:2023-08-24 20:12:31浏览次数:31  
标签:slope ch int 凸函数 trick 斜率 ans push

slope trick

概述

在 \(dp\) 过程中,可以维护凸函数的方法,要求 \(dp\) 值呈凸函数且其斜率均为整数。
具体来说,是记录凸函数斜率的变化值,即在什么位置斜率\(\plusmn 1\),例如凸函数 \(f(x) = |x|\),它由一条斜率为 \(-1\) 和 一条斜率为 \(1\) 的射线在 \(0\)点处相连,那么在零点处斜率加了 \(2\),所以可以用 \([0, 0]\) 来表示这个函数。

例题

1.【CF713C】Sonya and Problem Wihtout a Legend

严格递增可以通过减 \(i\) 变为不严格。
对于这题,我们容易想到 \(dp\),设 \(f_{i,j}\) 表示填了 \(1\) 到 \(i\) 位,第 \(i\) 位填 \(j\) 的最小操作次数,容易得到转移

\[f_{i,j} = \min_{k \le j} f_{i - 1,k} + |a_i - j| \]

设 \(g_{i,j} = \min_{k\le j}f_{i,k}\),可以归纳证明 \(f, g\) 均为凸函数。

我们可以考虑维护 \(g\) 的凸函数,那它一定是形如左边一段弯的接一条斜率为 \(0\) 的直线。
那么每一转移就相当于加上 一个凸函数\(|a_i - x|\),再做前缀\(min\)。
设当前函数最低点的横坐标为 \(x\),就有两种情况:
当 \(x \le a_i\) 时,我们相当于将 \(a_i\) 左侧的线段斜率减一,那么只需要多加入一个转折点 \(a_i\),即可。
当 \(x > a_i\) 时,这时我们是将 \(a_i\) 左侧的斜率减一,右侧加一,所以我们应该加入两个 \(a_i\),而最小值加上了\(x - a_i\),所以答案也加\(x - a_i\),因为我们要做一次前缀\(min\),所以要删去一个 \(x\)。
这些操作都可以用堆维护,时间复杂度为\(O(n \log n)\)

Code
#include<bits/stdc++.h>
#define LL long long
#define eb emplace_back
#define IN inline
using namespace std;
int n; 

IN int read() {
	int t = 0,res = 0; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) t |= (ch == '-');
	for (; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (ch ^ 48);
	return t ? -res : res;
}
priority_queue<int> Q;
int main() {
	n = read(); LL ans = 0;
	for (int i = 1; i <= n; i++) {
		int z = read() - i; Q.push(z);
		if (Q.top() > z) ans += (LL)Q.top() - z, Q.pop(), Q.push(z); 
	}
	printf("%lld\n", ans);
}

2. [ABC217H] Snuketoon

容易想到 \(dp\),设 \(f_{i,j}\) 表示经历了前 \(i\) 个事件,处于 \(j\) 受到的最小伤害,容易得到转移

\[f_{i,j} = \min_{k = j - (T_i - T_{i - 1})}^{j+(T_i - T_{i-1})}f_{i-1,k} + \max(0, X_i - j) or \max{0,j - X_i} \]

后面部分为凸函数,可以归纳出 \(f\) 也为凸函数。
可以用两个堆来维护这个下凸包,一个维护左凸壳,一个维护右凸壳。
那么对于\(min\)转移,相当于将凸壳向两边移动了\(T_i - T_{i - 1}\)。
而加入的凸函数只需像 例 \(1\) 一样判断即可。

Code
#include<bits/stdc++.h>
#define LL long long
#define eb emplace_back
#define IN inline
using namespace std;
int n; 

IN int read() {
	int t = 0,res = 0; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) t |= (ch == '-');
	for (; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (ch ^ 48);
	return t ? -res : res;
}
priority_queue<LL> Ql;
priority_queue<LL, vector<LL>, greater<LL> > Qr;
int main() {
	n = read(); LL tagl = 0, tagr = 0, ans = 0;
	for (int i = 1; i <= n + 1; i++) Ql.push(0), Qr.push(0);
	for (int i = 1, pt = 0; i <= n; i++) {
		int t = read(), d = read(); LL X = read();
		LL dt = t - pt;
		tagl -= dt, tagr += dt;
		if (d == 0) {
			LL u = Qr.top() + tagr;
			if (X > u) ans += X - u, Ql.push(u - tagl),Qr.pop(), Qr.push(X - tagr);
			else Ql.push(X - tagl);
		}
		else {
			LL u = Ql.top() + tagl;
			if (X < u) ans += u - X, Qr.push(u - tagr), Ql.pop(), Ql.push(X - tagl);
			else Qr.push(X - tagr);
		}
		pt = t;
	} 
	printf("%lld\n", ans);
}


标签:slope,ch,int,凸函数,trick,斜率,ans,push
From: https://www.cnblogs.com/nibabadeboke/p/17655051.html

相关文章

  • [Trick] [算法学习笔记] 线段树
    事先声明:本文并非线段树教学。只是一些理解Trick。若您需从0学起线段树建议您移步其他博文呢qwq感谢Idea提供尺子姐姐的博客!,尺子好闪,拜谢尺子!我们在学习线段树的时候,对于乘法“lazytag先乘再加”是不是难以理解?这里介绍一种线段树思考方法。我们可以将序列中的每个元素......
  • Dedecms V110最新版RCE---Tricks
    前言刚发现Dedecms更新了发布版本,顺便测试一下之前的day有没有修复,突然想到了新的tricks去实现RCE。文章发布的时候估计比较晚了,一直没时间写了。利用/uploads/dede/article_string_mix.php/uploads/dede/article_template_rand.php/uploads/dede/sys_task.php......我发......
  • Dedecms V110最新版RCE---Tricks
    前言刚发现Dedecms更新了发布版本,顺便测试一下之前的day有没有修复,突然想到了新的tricks去实现RCE。文章发布的时候估计比较晚了,一直没时间写了。利用/uploads/dede/article_string_mix.php/uploads/dede/article_template_rand.php/uploads/dede/sys_task.php......我发布的文......
  • 优化:深度神经网络Tricks【笔记】
    Slide:http://lamda.nju.edu.cn/weixs/slide/CNNTricks_slide.pdf博文:http://lamda.nju.edu.cn/weixs/project/CNNTricks/CNNTricks.html 1)dataaugmentation;    2)pre-processingonimages;     3)initializationsofNetworks;      4)sometips......
  • 【Tricks,典】[ARC085F] NRE
    一眼顶针,鉴定为implement不足,我写不出来。先通过Trick转化\(a_i=0\to-1,a_i=1\to1\)。那么显然把\([l,r]\)全部摊为1的贡献就是\(a_{l\tor}\)。转化为n-最大贡献。然后我们可以转化以下。\[f_i=f_j+a_r-a_{l-1}(r_j<l)\]\[f_i=f_j+a_r......
  • Slope Trick 学习笔记
    SlopeTrick学习笔记看算法名的时候还以为就是斜率优化一种维护DP的方法,需要满足DP式与斜率修改关系较大,比如:$$f_{i,j}=\min_{k<=j}(f_k)+|a_i-j|$$可以发现\(f_i\)关于\(j\)​的函数为凸函数,其斜率为正的部分显然没有必要保留令\(g_i=|a_i-j|\),\(g_i\)关于\(j\)......
  • 一些 tricks
    网络流最小割的可行边和必须边判定可行边:满流。在残余网络中找不到\(u\rightarrowv\)的路径。必须边:满流残余网络中源点能到入点,出点能到汇点。证明......
  • 一些 trick
    高次整除分块对\(\large\lfloor\frac{n}{i^2}\rfloor\)整除分块,\(\larger=\sqrt{\lfloor\frac{n}{\lfloor\frac{n}{l^2}\rfloor}\rfloor}\).容易发现对于\(i\len^{\frac{1}{3}}\)和\(i\gen^{\frac{1}{3}}\),都只有\(n^\frac{1}{3}\)种取值,所以复杂度\(O(n^{\fr......
  • trick : Trygub num
    trick大意我对于这个trick的理解为:支持位运算的高精度维护一个以\(b\)为基数的大数\(N\),并支持以下功能:给定(可能是负)整数\(|x|,|y|\leqslantn\),将\(xb^y\)加到\(N\)。\(N\geqslant0\)时,给定\(k\),打印\(N\)的第\(k\)位数字(指以\(b\)为基底意义下的)。检查\(N\)是正......
  • 深度学习刷SOTA的trick
    作者:GordonLeehttps://www.zhihu.com/question/540433389/answer/2549775065 1.R-Drop:两次前向+KLloss约束2.MLM:在领域语料上用mlm进一步预训练(Post-training)3.EFL:少样本下,把分类问题转为匹配问题,把输入构造为NSP任务形式.4.混合精度fp16:加快训练速度,提高训练......