土地购买 usaco 斜率优化

看这道题的时候,感觉很难,因为数据范围比较大,很难dp;

后来想到了【书柜的尺寸】这道题,也是一道dp,曾经看了那道题的题解而深有启发;

这道题每组的付费只与这一组长宽的最大值有关,也就是说要分组,一定从按长或宽的从大到小(从小到大也可以)排序,这样剔除无用的数据后,就只剩下一串数据,长从大到小,宽从小到大;

然后我们要在这里面分组,可以轻易发现,一个组的成员一定是连续的,原因与单调性有关;

这样就成了经典的dp,加上一个斜率优化即可轻松水过;

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<string>
 6 #include<algorithm>
 7 using namespace std;
 8 const int maxn=50500;
 9 #define LL long long
10 int n,q[maxn];
11 struct node{
12     int x,y;
13     bool operator<(const node& c)const{return (x>c.x)||(x==c.x&&y>c.y);}
14 }a[maxn],b[maxn];
15 LL f[maxn];
16 double col(int j,int k){return double(f[k]-f[j])/double(b[j+1].x-b[k+1].x);}
17 void init(){
18     scanf("%d",&n);
19     for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
20     sort(a+1,a+n+1);int head=1,tail=0;
21     b[++tail]=a[1];
22     for(int i=2;i<=n;i++)if(a[i].y>b[tail].y)b[++tail]=a[i];
23     n=tail;
24     head=1,tail=0;q[++tail]=0;
25     for(int i=1;i<=n;i++){
26         while(head<tail&&col(q[head],q[head+1])<=b[i].y)head++;
27         f[i]=f[q[head]]+(LL)b[q[head]+1].x*b[i].y;
28         while(head<tail&&col(q[tail],i)<=col(q[tail],q[tail-1]))tail--;
29         q[++tail]=i;
30     }
31     cout<<f[n]<<endl;
32 }
33 int main(){
34     init();
35 }
View Code

 

posted @ 2016-09-09 13:47  CHADLZX  阅读(247)  评论(0编辑  收藏  举报