luogu2900:Land Acquisition(斜率优化)
题意:有N块地,每块地给出的宽和高,然后可以分批买,每次买的代价是所选择的地种最宽*最高。 问怎么买,使得代价和最小。
思路:显然,先去掉被包括的情况,即如果一个地的宽和高斗比另外一个小,那么久可以删去。 这样,我们得到一些的地宽递增,高递减; 然后得到方程:
dp[i]=min(dp[j]+w[i]*h[j+1]);斜率优化即可。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=200010; struct in{ int w,h; bool friend operator <(in p,in q){ return (p.w^q.w)?p.w<q.w:p.h<q.h; } }s[maxn],y[maxn]; ll dp[maxn]; int q[maxn],head,tail; int main() { int N,M,tot=0; scanf("%d",&N); rep(i,1,N) scanf("%d%d",&s[i].w,&s[i].h); sort(s+1,s+N+1); for(int i=N;i>=1;i--){ if(tot&&y[tot].h>s[i].h) continue; y[++tot]=s[i]; } rep(i,1,tot) s[i]=y[tot+1-i]; N=tot; q[++head]=0; //tail<=head; rep(i,1,N) { while(tail<head&&1.0*(dp[q[tail+1]]-dp[q[tail]])/(-s[q[tail+1]+1].h+s[q[tail]+1].h)<1LL*s[i].w) tail++; dp[i]=dp[q[tail]]+1LL*s[i].w*s[q[tail]+1].h; while(tail<head&&1.0*(dp[i]-dp[q[head]])/(-s[i+1].h+s[q[head]+1].h)<=1.0*(dp[i]-dp[q[head-1]])/(-s[i+1].h+s[q[head-1]+1].h)) head--; q[++head]=i; } printf("%lld\n",dp[N]); return 0; }
It is your time to fight!