题目:
农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <
= 1,000,000; 1 <= 长 <= 1,000,000). 每块土地的价格是它的面积,但FJ可以同时购买多快土地. 这些土地的价
格是它们最大的长乘以它们最大的宽, 但是土地的长宽不能交换. 如果FJ买一块3x5的地和一块5x3的地,则他需要
付5x5=25. FJ希望买下所有的土地,但是他发现分组来买这些土地可以节省经费. 他需要你帮助他找到最小的经费.
题解:
零.
乱序,乱跑.
没有任何思路洗洗睡吧
O(1)O(1)O(1)最强算法rand()
(:逃
一.
以x为第一关键字排序,就只用(线性)顺序跑了
f[i]=min(f[j]+max(y[k])×x[i])(j+1≤k≤i)f[i]=min(f[j]+max(y[k])\times x[i])(j+1\leq k\leq i)f[i]=min(f[j]+max(y[k])×x[i])(j+1≤k≤i)
O(n3)O(n^3)O(n3)爆炸
二.
找规律发现有些点绝对不会作为max点
什么点,x,y都比至少一个别人小的点
那我怎么知道哪些点是满足的?

大概把点转移在图中,(秘籍·大眼观察法)发现维护一个下降的y,其他的丢掉就行了。
脑补一下,x已经前面比后面小了,要是y还比后面小,那就没面子了,还不如去死呢。。
然后min(y[k])−>y[j+1]min(y[k])->y[j+1]min(y[k])−>y[j+1]
O(n2)O(n^2)O(n2)但还是不行
三.
f[i]=f[j]+y[j+1]×x[i]f[i]=f[j]+y[j+1]\times x[i]f[i]=f[j]+y[j+1]×x[i]
模版:fi=ai×fj+bi×gjf_i=a_i\times f_j+b_i\times g_jfi=ai×fj+bi×gj
非常简单的 斜率优化
O(n)O(n)O(n) OK走人
//没找到评测系统,未评测,未知正确性
#include<bits/stdc++.h>
#define ll long long
#define X(x) b[x+1].y
#define Y(x) dp[x]
using namespace std;
const int N=5e4+10,INF=1e9;
int n;
struct qw{
int x,y;
bool operator < (const qw a)const{return x==a.x?y<a.y:x<a.x;}
}a[N],b[N];
int p;
int dp[N];
int z[N],p1=1,p2=1;
double kt(int i,int j)
{
return (double)(Y(i)-Y(j))/(double)(X(i)-X(j));
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+n+1);
b[0].y=INF;
for(int i=1;i<=n;i++)
{
while(p&&b[p].y<a[i].y)p--;
b[++p]=a[i];
}
//for(int i=1;i<=p;i++)printf("(%d,%d)\n",b[i].x,b[i].y);
for(int i=1;i<=p;i++)
{
while(p1<p2&&kt(z[p1],z[p1+1])>1.0*(-b[i].x))p1++;
int j=z[p1];
dp[i]=dp[j]+b[i].x*b[j+1].y;
while(p1<p2&&kt(z[p2-1],z[p2])>kt(z[p2],i))p2--;
z[++p2]=i;
}
printf("%d",dp[p]);

探讨农夫John如何通过最优策略购买N块长方形土地以节省总费用。介绍了几种算法思路,包括O(n^3)、O(n^2)和最终的O(n)最优算法,展示了如何通过斜率优化实现高效求解。

177

被折叠的 条评论
为什么被折叠?



