/*
这题是斜率优化的入门题
浅谈数形结合在信息学竞赛中的应用中讲得很好,这是其中的例二;
在此标记个人理解上觉得重要的地方;
首先这题求max{(s[i]-s[j])/(i-j)}即看成求最大斜率...
*/
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
const int NN=100005;
int n,k,f,r;
LL s[NN];
struct node
{
int x;
LL y;
node(){}
node(int _x,int _y):x(_x),y(_y){}
}q[NN];
LL mult(node p1,node p2,node p0)
//比较斜率检查队尾是否是上凸点
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
LL get() //用scanf时TLE了,用外挂才过(400ms+)
{
char ch;
LL ret=0;
while ((ch=getchar())==' ' || ch=='\n');
ret=ch-'0';
while ((ch=getchar())!=' ' && ch!='\n') ret=ret*10+ch-'0';
return ret;
}
int main()
{
int f,r;
double ans;
while (scanf("%d%d",&n,&k)!=EOF)
{
s[0]=0;
for (int i=1; i<=n; i++)
{
s[i]=get();
s[i]+=s[i-1];
}
f=-1; r=0; ans=0.0;
for (int i=k; i<=n; i++)
{
node tmp=node(i-k,s[i-k]); //加入点i-k到队列,保证长度不小于k
while (f<r && mult(q[r],tmp,q[r-1])<=0) r--;//维持队列的'单调性',除去上凸点
q[++r]=tmp;
while (f<r && (s[i]-q[f].y)*(i-q[f+1].x)<=(s[i]-q[f+1].y)*(i-q[f].x)) f++;
//一直不能理解为什么仅由当前点的最值,就去掉队列首部最值之前的点,
//这样完全可能会去掉后面的点dp到的最大值啊,
//画图想了很久之后才理解,这样确实可能去掉某些点的最大斜率,
//但去掉的这些点的最大斜率一定不是整个程序的最大值,
//一心想着求出当前最值的思维限制了程序的优化,
//如果要求求出每个i的max{(s[i]-s[j])/(i-j)}就不能这么写了
ans=max(ans,(double)(s[i]-q[f].y)/(double)(i-q[f].x));
}
printf("%.2f\n",ans);
}
return 0;
}
Hdu-2993斜率优化
最新推荐文章于 2019-09-19 20:23:08 发布