文文殿下 [USACO08MAR]土地征用 题解
Posted syameimaru
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文文殿下 [USACO08MAR]土地征用 题解相关的知识,希望对你有一定的参考价值。
题解
斜率优化裸题。
有个很玄学的事情,就是我用(f[i]=min{f[j-1]+p[j].y*p[i].x}) 会很奇怪的Wa 。 明明和(f[i]=min{f[j]+p[j+1].y*p[i].x})一模一样的呀!
如果有dalao愿意帮忙看一下就感激不尽了。
附上正确代码和错误代码
正确代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 5e4+10;
const ll inf = 10000000000000LL;
struct qwq{
ll x,y;
const bool operator < (const qwq rhs) const {
if(this->x==rhs.x)
return this->y<rhs.y;
return this->x<rhs.x;
}
} tmp[maxn],p[maxn];
ll f[maxn];
int tot=0,n,q[maxn],l,r;
long double slope(int a,int b) {
long double tmp1 = f[b]-f[a],tmp2 = -p[b+1].y+p[a+1].y;
return tmp1/tmp2;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i = 1;i<=n;++i)
cin>>tmp[i].x>>tmp[i].y;
sort(tmp+1,tmp+1+n);
ll mxy=0;
for(int i = n;i;--i) {
if(tmp[i].y>mxy) {
mxy=tmp[i].y;
p[++tot]=tmp[i];
}
}
reverse(p+1,p+1+tot);
#ifdef force
for(int i = 1;i<=tot;++i) {
f[i]=inf;
for(int j = 0;j<i;++j) {
f[i]=min(f[i],f[j]+p[j+1].y*p[i].x);
}
}
#endif
#ifndef force
for(int i = 1;i<=tot;++i) {
while(l<r&&slope(q[l],q[l+1])<=p[i].x) ++l;
int j = q[l];
f[i]=f[j]+p[j+1].y*p[i].x;
while(l<r&&slope(q[r-1],q[r])>=slope(q[r],i)) --r;
q[++r]=i;
}
#endif
cout<<f[tot]<<endl;
return 0;
}
错误代码
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 5e4+10;
const ll inf = 10000000000000LL;
double esp = 1e-6;
struct qwq{
ll x,y;
const bool operator < (const qwq rhs) const {
if(this->x==rhs.x)
return this->y<rhs.y;
return this->x<rhs.x;
}
} tmp[maxn],p[maxn];
ll f[maxn];
int tot=0,n,q[maxn],l,r;
double slope(int a,int b) {
double tmp1 = f[b-1]-f[a-1],tmp2 = -p[b].y+p[a].y;
return tmp1/tmp2;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i = 1;i<=n;++i)
cin>>tmp[i].x>>tmp[i].y;
sort(tmp+1,tmp+1+n);
ll mxy=0;
for(int i = n;i;--i) {
if(tmp[i].y>mxy) {
mxy=tmp[i].y;
p[++tot]=tmp[i];
}
}
reverse(p+1,p+1+tot);
#ifdef force
for(int i = 1;i<=tot;++i) {
f[i]=inf;
for(int j = 1;j<=i;++j) {
f[i]=min(f[i],f[j-1]+p[j].y*p[i].x);
}
}
#endif
#ifndef force
l=r=1;
q[1]=1;
for(int i = 1;i<=tot;++i) {
while(l<r&&slope(q[l],q[l+1])<=p[i].x) ++l;
int j = q[l];
f[i]=f[j-1]+p[j].y*p[i].x;
while(l<r&&slope(q[r-1],q[r])>=slope(q[r],i)) --r;
q[++r]=i+1;
}
#endif
cout<<f[tot]<<endl;
return 0;
}
以上是关于文文殿下 [USACO08MAR]土地征用 题解的主要内容,如果未能解决你的问题,请参考以下文章
[USACO08MAR]土地征用Land Acquisition
洛谷P2900 [USACO08MAR]土地征用Land Acquisition
[USACO08MAR]土地征用Land Acquisition
Luogu 2900 [USACO08MAR]土地征用Land Acquisition