首页 > 其他分享 >斜率优化DP简单总结&&“土地购买”题解

斜率优化DP简单总结&&“土地购买”题解

时间:2024-06-10 17:11:12浏览次数:15  
标签:前缀 题解 斜率 && 优化 DP 式子

今天刚刷完了斜率优化DP,简单从头回顾一下。

\[首先,能写出DP方程应该是最重要的,毕竟斜率只是用来优化的 \]

那么一个DP方程能用斜率优化,具备一种形式:

\[f[i]+s1[i]+A[i]*B[j]=f[j]+s2[j] \]

其中,f[i]表示所求值,(s1[i]、A[i])与(s2[j]、B[j])分别表示只与i或j有关的一个表达式(可以是只有常数项)。

然后就可以建立一个横坐标为B[j],斜率为A[i],纵坐标为f[j]+s2[j]的函数。如果横坐标有单调性,那么只需单调队列保留一个凸壳或凹壳即可(任务安排2),否则就像需要支持任意插入、查询(任务安排3、4)。


基本形式大概就是上面那样,接下来从题中看点特别的。

1、任务安排系列

  • 我们使用了费用提前计算思想。
  • 通过前缀和使得整个式子只包含与i,j有关的变量和常数,通过移项,使得式子简化成f[i]+s1[i]+A[i]*B[j]=f[j]+s2[j]的形式,直接省去了j的枚举,时间复杂度降到O(N)。

2、运输小猫

  • 通过每只小猫的游玩时间和位置信息,将其与饲养员出发时间建立联系,便与任务安排很像了。
  • 同样使用前缀和将所有变量转为只与i,j有关的变量,最终式子化简为标准形式,时间O(N)。

3、特别行动队、仓库建设、玩具装箱

  • 几乎没什么区别,将DP方程写出来之后,通过前缀和去化简变量,最终简化式子为标准形式即可。
从上面的这些题中可以看出,我们大量运用了前缀和,就是为了可以通过预处理将DP方程中的变量简化为只与i,j有关的量,以便将式子化为标准形式,$$所以斜率优化DP就是要去简化变量,转化式子,剩下的就可以斜率优化掉一层枚举了$$

4、但是前缀和并不万能,来看 “土地购买”

image

首先毫无头绪,没有像前几道题那样点明必须连续购买,而是想买多少卖多少,这朴素转移就很难,pu-tao↑。
但是为了比较好判断谁的l(长)比较大,先把他们按l sort一遍,得到一个a不严格递增的序列,由前几道题的做题经验想到应该取连续的一段,来证明一下:

反证 :

如果不应该取连续的一段,那么就是取不连续的,num[i]表示i在序列中的位置,设num[a]<num[b]<num[c],取a,c,不取b。
如果取c不取b,说明w[c](宽)<w[b],不然w[c]>w[b]&&l[c]>l[b]就必然会把b包括进来,接下来分类讨论一下:

  1. w[a]<=w[b]:
    image
    显然b可以包括进a,不行。
  2. w[a]>w[b]:
    image
    (1):w[a]是b所包括范围之内最大的w
    ①:w[a]是c所包括范围之内最大的w,因为l[b]<=l[c],所以a属于b更优。
    ②:w[a]不是c所包括范围之内最大的w,那就可以把c所包括的最大的w[x]的x给b,因为l[b]<=l[c].
    (2):w[a]不是b所包括范围之内最大的w,那么a不会对b的答案造成影响,给b更优。
    所以a应该跟b,即不连续的取一段不是最优解。
证毕

由上述证明过程引发出一个想法:$$ w[i]>w[j]\ and\ l[i]>l[j],j完全可以被i包含,j无用 $$,所以整个序列要去掉那些无用的元素,用以w为关键字单调递减队列跑一遍,即可得到最终序列,l递增,w递减:
image

由此可以写出DP方程:$$f[i]=f[j]+l[i]*w[j+1]$$,完美符合标准形式,切横坐标-w[j+1]具有单调性,直接跑单调队列即可。

pu-tao↑zher↑↓
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define laoda MAN
#define MAN What Can I Say?
typedef long long ll;
typedef pair<int,int> pii;
const ll linf=0x3f3f3f3f7fffffff;
inline int read(){
	char c=getchar();int x=0;
	bool f=1;
	while(c<'0'||c>'9')f=c=='-'?0:1,c=getchar();
	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return f==0?-x:x;
}
const int N=5e4+10,inf=0x7f7f7f7f;
ll n,f[N],q[N],l=1,r,m[N];
struct jj{
	ll a,b;//a->l,b->w
	inline bool operator <(const jj &x)const{
		return a<x.a;
	}
}man[N];
int main(){
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	freopen("out.out","w",stdout);
	#endif	
	n=read();
	for(int i=1;i<=n;++i){
		man[i]={read(),read()};
	}
	sort(man+1,man+1+n);
	for(int i=1;i<=n;++i){
		while(l<=r&&man[q[r]].b<=man[i].b)--r;
		q[++r]=i;
	}
	for(int i=l;i<=r;++i)
		man[i-l+1]=man[q[i]];
	n=r-l+1;
	l=1,r=1;q[1]=0;
	for(int i=1;i<=n;++i){
		int j=q[l+1],k=q[l];
		while(l<r&&f[j]-f[k]<=man[i].a*(man[k+1].b-man[j+1].b))k=q[++l],j=q[l+1];
		f[i]=f[k]+man[i].a*man[k+1].b;
		j=q[r],k=q[r-1];
		while(l<r&&(f[j]-f[k])*(man[i+1].b-man[j+1].b)<=(f[i]-f[j])*(man[j+1].b-man[k+1].b))j=q[--r],k=q[r-1];
		q[++r]=i;
	}
	cout<<f[n];
}

标签:前缀,题解,斜率,&&,优化,DP,式子
From: https://www.cnblogs.com/GGrun-sum/p/18240822

相关文章

  • Codeforces Round 837题解(A、B)
    A.HossamandCombinatorics\(|a_i-a_j|\)最大的就是最大值和最小值,注意要开longlong。intn;inta[N];voidsolve(){cin>>n;intmin_v=INF,max_v=0;for(inti=1;i<=n;i++){cin>>a[i];min_v=min(min_v,a[i......
  • CF1970F1 Playing Quidditch (Easy) 题解
    一道大模拟题。这道题可以用一个 map 记录球员及鬼飞球当时的坐标,用一个数组 a 记录是否有人进球,用另一个数组 b 记录每位球员是否有鬼飞球。当球员抓住鬼飞球后,鬼飞球跟着这个球员移动,直到这个球员投球。话不多说,直接上代码。MyCode:#include<bits/stdc++.h>#de......
  • 【题解】 [CSP-J 2019] 纪念品
    题目描述题目大意在\(T\)天内,有\(n\)种纪念品和初始的\(m\)元。可以得到每天每种纪念品的价格。每一天可以以当日价格买卖纪念品。特别的,当天卖出得到的钱可以当天买入,当日买入的纪念品也可以当日卖出。当然可以一直持有。但是,\(T\)天过后,手上不可以持有纪念品。思路......
  • 【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 机场航班调度程序(100分) - 三语言A
    ......
  • 【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 最富裕的小家庭(100分) - 三语言AC
    ......
  • P7690 [CEOI2002] A decorative fence 题解
    cnblogs如果只是询问方案数,是P2467[SDOI2010]地精部落这道题,设\(f_{i,j,1/0}\)表示以\(j\)个数中从小到大的第\(i\)个数处于高/低位开头的方案数。显然有\[\begin{aligned}\begin{cases}f_{i,j,1}=\sum_{k=1}^{i-1}f_{k,j-1,0}\\f_{i,j,0}=\sum_{k=i}......
  • WQS 二分 & 凸优化dp
    WQS二分决策单调性,四边形不等式\(O(nk\logn)\toO(n\logn)\)想法转移转成最短路。最短路,转移代价\(\to\)边权。恰好选k条边的最短路为\(f\)。\(f\)必须有凸性。加上额外代价\(\lambda\):\(\lambda\to\inf\),选1边\(\lambda\to-\inf\),选n边二......
  • 【QT5】<总览五> QT多线程、TCP/UDP
    文章目录前言一、QThread多线程二、QT中的TCP编程1.TCP简介2.服务端程序编写3.客户端程序编写4.服务端与客户端测试三、QT中的UDP编程1.UDP简介2.UDP单播与广播程序前言承接【QT5】<总览四>QT常见绘图、图表及动画。若存在版权问题,请联系作者删除!一、QThre......
  • 【NAS】Docker Gitea+SakuraFrp+绿联DPX4800标 搭建私有代码托管平台
    本文主要分享Gitea的一些设置,和Https的实现。Gitea的一些设置映射网络HTTPS的实现先准备好一个域名,建议准备一个1Panel创建一个AC账户然后点击申请证书,手动解析。申请完毕后,点击详情,查看证书crt和私钥key自己创建一个txt文本,将证书crt粘贴进去,然后将名字改为xxx.crt......
  • UDP报文结构
    学习一个协议,首先就是去理解它的报文结构。UDP数据报可以分为报头与载荷两个部分。报头占八个字节,分别是源端口号,目的端口号,udp报文长度,UDP校验和,每个部分占两个字节。载荷是完整的应用层的数据报。报头和载荷可以认为是“拼接“在一起。UDP报文长度:是一个两个字节的16位的......