土地购买 (斜率优化dp)
土地购买 (斜率优化dp)
题目描述
农夫 \(John\) 准备扩大他的农场,他正在考虑$ N(1 \leqslant N \leqslant 50,000)$ 块长方形的土地. 每块土地的长宽满足\((1 \leqslant\) 宽 \(\leqslant 1,000,000; 1 \leqslant\) 长 \(\leqslant 1,000,000)\).
每块土地的价格是它的面积,但 \(FJ\) 可以同时购买多块土地. 这些土地的价格是它们最大的长乘以它们最大的宽, 但是土地的长宽不能交换. 如果 \(FJ\) 买一块 \(3\times 5\) 的地和一块 \(5\times 3\)的地,则他需要付 \(5\times 5=25\).
\(FJ\) 希望买下所有的土地,但是他发现分组来买这些土地可以节省经费. 他需要你帮助他找到最小的经费.
输入格式
第 \(1\) 行:一个数: \(N\)
第 \(2..N+1\) 行:第 \(i+1\) 行包含两个数,分别为第 \(i\) 块土地的长和宽。
输出格式
第一行: 最小的可行费用。
样例
样例输入
4
100 1 15 15 20 5 1 100
样例输出
500
样例解释
共有 \(4\) 块土地,\(FJ\) 分 \(3\) 组买这些土地: 第一组: \(100\times 1\), 第二组 \(1\times 100\) , 第三组 \(20\times 5\) 和 \(15\times 15\) 每组的价格分别为 \(100,100,300\) , 总共 \(500\)。
数据范围与提示
对于 \(50\%\) 的数据 \(n \leqslant 1000\)
对于 \(100\%\) 的数据 \(n \leqslant 50000\)
数据有一定梯度
分析
题目中说选一堆土地的时候,只用最大的长和宽计算价值,那么我们可以先去重,也就是让包含的关系先处理掉,按照长度从小到大排序,利用一个单调栈来维护单调减的一堆序列,这样就去完了重(所谓的去重),这时候长度就是递增,宽度递减,那么我们只需要取一段区间的端点即可,转化成状态转移方程就是:
\]
转化一下柿子,变成 \(f[j-1] = f[i] - len_j \times width_i\)
最后这个式子就可以用来斜率优化了。
代码
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int L=1<<20;
char buffer[L],*S,*T;
#define lowbit(x) (x & -x)
#define getchar() (S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T)?EOF:*S++)
#define inline __inline__ __attribute__((__always_inline__))
#define max(a,b) (a>b?a:b)
#define re register
#define ll long long
const int maxn = 5e4+10;
ll f[maxn];
struct Node{
ll w,l;
}jl[maxn];
ll staw[maxn];
int top;
ll stal[maxn];
ll q[maxn];
ll a[maxn],b[maxn];
inline ll read(){
int s = 0,f = 1;
char ch = getchar();
while(!isdigit(ch)){
if(ch == '-')f = -1;
ch = getchar();
}
while(isdigit(ch)){
s = s * 10 + ch - '0';
ch = getchar();
}
return s * f;
}
inline bool cmp(Node a,Node b){//排序
if(a.l == b.l)return a.w < b.w;
return a.l < b.l;
}
inline ll calc(int a,int b){//计算函数值
return f[b] + staw[b+1] * stal[a];
}
inline bool jud(int x1,int x2,int x3){//计算斜率
return (b[x3] - b[x1]) * (a[x2] - a[x1]) >= (b[x2] - b[x1]) * (a[x3] - a[x1]);
}
signed main(){
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
re ll n = read();
for(re int i = 1;i <= n;++i){
jl[i].w = read();
jl[i].l = read();
}
sort(jl+1,jl+n+1,cmp);
for(re int i = 1;i <= n;++i){//单调栈去重,找出包含的情况
while(top && jl[i].w >= staw[top])top--;
staw[++top] = jl[i].w;
stal[top] = jl[i].l;
}
re int head = 1,tail = 1;
a[0] = staw[1];
for(re int i = 1;i <= top;++i){//单调队列斜率优化
while(head < tail && calc(i,q[head]) >= calc(i,q[head+1]))head++;
f[i] = calc(i,q[head]);
a[i] = staw[i + 1];
b[i] = f[i];
while(head < tail && jud(q[tail-1],q[tail],i))tail--;
q[++tail] = i;
}
printf("%lld\n",f[top]);
return 0;
}
土地购买 (斜率优化dp)的更多相关文章
- bzoj 1597 [Usaco2008 Mar]土地购买——斜率优化dp
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1597 又一道斜率优化dp.负数让我混乱.不过仔细想想还是好的. 还可以方便地把那个负号放到x ...
- 【BZOJ1597】【Usaco2008 Mar】土地购买 斜率优化DP
题目: 题目在这里 思路与做法: 这题如果想要直接dp的话不太好处理. 不过, 我们发现如果\(a[i].x>=a[j].x\)且\(a[i].y>=a[j].y\) \((\)a是输入的 ...
- BZOJ 1597: [Usaco2008 Mar]土地购买 [斜率优化DP]
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4026 Solved: 1473[Submit] ...
- BZOJ 1597 土地购买(斜率优化DP)
如果有一块土地的长和宽都小于另一块土地的长和宽,显然这块土地属于“赠送土地”. 我们可以排序一下将这些赠送土地全部忽略掉,一定不会影响到答案. 那么剩下的土地就是长递减,宽递增的.令dp[i]表示购买 ...
- BZOJ1597:[USACO]土地购买(斜率优化DP)
Description 农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 < = 1,000 ...
- bzoj1597[Usaco2008 Mar]土地购买 斜率优化dp
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5524 Solved: 2074[Submit] ...
- bzoj1597/luogu2900 土地购买 (斜率优化dp)
首先按x从小到大排序,那么可得: f[i]=min{f[j]+x[i]*maxy[j+1..i]} 然而这样是$O(n^2)$的而且无法做优化. 然后我们考虑:如果对于某一点,存在另一点的x和y都比它 ...
- bzoj1597 [Usaco2008 Mar]土地购买——斜率优化DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1597 就是斜率优化水题... 然而WA了十几遍,正负号处理真让人心累... 还是该负就负,别 ...
- [Bzoj1597][Usaco2008 Mar]土地购买(斜率优化)
题目链接 因为题目说可以分组,并且是求最值,所以斜率优化应该是可以搞的,现在要想怎么排序使得相邻的数在一个组中最优. 我们按照宽$w$从小到大,高$h$从小到大排序.这时发现可以筛掉一些一定没有贡献的 ...
- BZOJ 1597: [Usaco2008 Mar]土地购买 斜率优化
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MB Description 农夫John准备扩大他的农场,他正在考虑N ...
随机推荐
- 看了这篇你就会手写RPC框架了
一.学习本文你能学到什么? RPC的概念及运作流程 RPC协议及RPC框架的概念 Netty的基本使用 Java序列化及反序列化技术 Zookeeper的基本使用(注册中心) 自定义注解实现特殊业务逻 ...
- 初识Elastic search—附《Elasticsearch权威指南—官方guide的译文》
本文作为Elastic search系列的开篇之作,简要介绍其简要历史.安装及基本概念和核心模块. 简史 Elastic search基于Lucene(信息检索引擎,ES里一个index—索引,一个索 ...
- 【Python】Async异步等待简单例子理解
import time def run(coroutine): try: print("") coroutine.send(None) except StopIteration a ...
- Android实现QQ登录
https://www.jianshu.com/p/e59bc198e88f
- git命令常用操作
第一步:拉取git上的文件(git clone 远程仓库地址) 第二步:在主目录下运行git base here,执行git status 第三步:添加文件到本地仓库(git add 文件)之后,再次 ...
- JVM详解之:汇编角度理解本地变量的生命周期
目录 简介 本地变量的生命周期 举例说明 优化的原因 总结 简介 java方法中定义的变量,它的生命周期是什么样的呢?是不是一定要等到方法结束,这个创建的对象才会被回收呢? 带着这个问题我们来看一下今 ...
- Python while 中简单的语句组
Python while 中简单的语句组: 只使用 while: # 简单的语句组 a = 4 b = 8 num = 0 while a < b: print("a 比 b 小&qu ...
- PHP is_array() 函数
is_array() 函数用于检测变量是否是一个数组.高佣联盟 www.cgewang.com PHP 版本要求:PHP 4, PHP 5, PHP 7 语法 bool is_array ( mixe ...
- C语言中的数据转换和定义常量
一.数据转换 1.数据类型转换:C 语言中如果一个表达式中含有不同类型的常量和变量,在计算时,会将它们自动转换为同一种类型:在 C 语言中也可以对数据类型进行强制转换: 2.自动转换规则: a)浮点数 ...
- x86架构:保护模式下利用中断实现抢占式多任务运行
站在用户角度考虑,一个合格的操作系统即使在单核下也能 "同时" 执行多个任务,这就要求CPU以非常快的频率在不同任务之间切换,让普通人根本感觉不到任务的切换.windwo ...