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 }