【文文殿下】 [USACO08MAR]土地征用 題解
阿新 • • 發佈:2019-01-18
include ret esp fde lin const code ble inline
題解
斜率優化裸題。
有個很玄學的事情,就是我用\(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]土地征用 題解