UPD:我真不是想骗访问量TAT。。一开始没注意总长度写着写着网页崩了王仓(其实中午的时候就时常开始卡了= =)。。。。损失了2h(幸好长一点的都单独开了一篇)。。。。吓得赶紧分成两坨。。。。TAT。。。。。。。。。。。。。。

——————————————————————————————————————————————————————————————————————————————

  写(被虐)了整整一个月b站上usaco的金组题。。。然而到现在总共只写了100道上下TAT(当然是按AC人数降序排列的了)(另外,是用云神的号写的= =毕竟三百大洋)

  大概不到1\3是自己写的,一半是有大概方向后跑去看题解,剩下的就是毫无思路就去看题解作死的了= =

  感觉金组题还是比较适合自己当前水平的QAQ。。。所以大致的写下题解加深下印象吧。。。对于比较经典而自己又不熟的题打算专门另写题解(瞬间就挖了一个大坑)

这里贴出50道。。。

 

bzoj 1597:[Usaco2008 Mar]土地购买    

  斜率优化入门题。f[i]表示买前i块土地的最小费用

  f[i]=min{
      f[j]+max_w(j+1,i)*max_l(j+1,i),( 0<=j<i )
  }// max_w(j+1,i)和max_l(j+1,i)分别表示第j+1块土地到第i块土地中宽度和长度的最大值

  首先去掉那些被别的土地完全覆盖的土地(因为不会对答案有任何影响),剩下的按宽度排序。宽度升序排序的话,长度一定是降序的(被完全覆盖的都被去掉了)

  方程就变成  f[i]=min{  f[j]+wid[i]*len[j+1]  },(0<=j<i)

  剩下的就是斜率优化了。。。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define d double
 6 #define ll long long
 7 using namespace std;
 8 const int maxn=50023;
 9 struct zs{
10     int x,y;
11 }a[maxn];
12 bool cant[maxn];
13 ll f[maxn];
14 int l,r,dl[maxn];
15 int i,j,k,n,m;
16 char rx;int ra;
17  
18  
19 bool cmp(zs a,zs b){return a.x<b.x||(a.x==b.x&&a.y>b.y);
20 }
21 bool smaller(int aa,int b,int c){
22     return  (ll)(f[c]-f[b])*(ll)(a[aa+1].y-a[b+1].y) <= (ll)(f[b]-f[aa])*(ll)(a[b+1].y-a[c+1].y);
23     /*return (d)(f[i]-f[dlr])/(d)(a[dlr+1].y-a[i+1].y)
24             <
25            (d)(f[dlr]-f[pre])/(d)(a[pre+1].y-a[dlr+1].y);*/
26 }
27 inline int read(){
28     rx=getchar();ra=0;
29     while(rx<'0'||rx>'9')rx=getchar();
30     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
31 }
32 int main(){
33     n=read();
34     for(i=1;i<=n;i++)a[i].x=read(),a[i].y=read();
35     sort(a+1,a+1+n,cmp);int tmp=a[n].y;
36     for(i=n-1;i;i--)
37         if(a[i].y<=tmp)cant[i]=1;else tmp=a[i].y;  tmp=0;
38     for(i=1;i<=n;i++)if(!cant[i])a[++tmp].x=a[i].x,a[tmp].y=a[i].y;  n=tmp;
39     for(i=1;i<=n;i++){
40         while(l<r&&  (ll)(f[dl[l+1]]-f[dl[l]]) < (ll)a[i].x*(ll)(a[dl[l]+1].y-a[dl[l+1]+1].y)  )l++;
41         f[i]=f[dl[l]]+(ll)a[i].x*a[dl[l]+1].y;
42         while(l<r&& smaller(dl[r-1],dl[r],i))r--;dl[++r]=i;
43     }
44     printf("%lld\n",f[n]);
45     return 0;
46 }
View Code

相关文章: