bzoj1597: [Usaco2008 Mar]土地购买
题目链接
题解
按照x,y降序排序
发现当$ x_i \leq x_j$ 且$ y_i \leq y_j$时,分在同一组的话是可以合并的...
合并之后的序列x不降,y单减
然后dp方程就好写了吧
然后斜率优化一下就可以了吧 QUQ
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
return x * f;
}
#define int long long
const int maxn = 50007;
struct Block {
int x,y;
bool operator < (const Block &a)const {
if(x == a.x) return y < a.y;
else return x < a.x;
}
}block[maxn];
int x[maxn],y[maxn],q[maxn];
int n,dp[maxn];
double slop(int k,int j) {
return double (dp[j] - dp[k] ) / double (y[k + 1] - y[j + 1]);
}
//dp[i] = min{ dp[j] + a[i] * b[j + 1] }
main() {
n = read();
for(int i = 1;i <= n;++ i) {
block[i].x = read();
block[i].y = read();
}
std::sort(block + 1,block + n + 1);
int tot = 0;
for(int i = 1;i <= n;++ i) {
while(tot && block[i].y >= y[tot]) tot --;
x[++ tot] = block[i].x;y[tot] = block[i].y;
}
int l = 0,r = 0;
for(int i = 1;i <= n;++ i) {
while(l < r && slop(q[l],q[l + 1]) < x[i] ) l ++;
int t = q[l];
dp[i] = dp[t] + y[t + 1] * x[i];
while(l < r && slop(q[r],i) < slop(q[r - 1],q[r]) ) r--;
q[++ r] = i;
}
printf("%lld\n",dp[tot]) ;
return 0;
}