poj2018 Best Cow Fences(直接求斜率)

xiaoxiao2021-02-28  114

这道题算是给斜率优化dp打下一个基础。题目要求的平均值,用前缀和表示的话就是 ave(i,j)=SjSi1j(i1) ,如果将S函数绘在平面直角坐标系内,这就是过点Sj和点Si-1直线的斜率!于是问题转化为:平面上已知N+1 个点,Pi(i, Si),0≤i≤N,求横向距离大于等于F的任意两点连线的最大斜率。构造下凸曲线,用双端队列维护就可以了。具体证明可以参见周源2004IOI国家集训队论文。应该可以在网上搜到吧,搜不到可以去我的资源下。。。

#include<cstdio> #include<cstring> int const N=100000+10; int n,f,s[N],q[N],h=0,t=1;//q中至少有两个点才做判断 float ans,temp=0; int main(){ // freopen("poj2018.in","r",stdin); scanf("%d%d",&n,&f); for(int i=1;i<=n;++i){ int x;scanf("%d",&x);s[i]=s[i-1]+x; } q[++h]=0;ans=(float)(s[f]-s[0])/f; for(int i=1;i+f<=n;++i){ while(h<t&&(s[i]-s[q[t]])*(q[t]-q[t-1])<=(s[q[t]]-s[q[t-1]])*(i-q[t])) --t; q[++t]=i; while(h<t&&(s[i+f]-s[q[h]])*(i+f-q[h+1])<(s[i+f]-s[q[h+1]])*(i+f-q[h])) ++h; temp=(float)(s[i+f]-s[q[h]])/(i+f-q[h]); if(ans<temp) ans=temp; } printf("%d",(int)(1000*ans)); return 0; }
转载请注明原文地址: https://www.6miu.com/read-31987.html

最新回复(0)