您的位置:首页 > 其它

Hdu-2993斜率优化

2012-07-23 10:44 211 查看
/*
这题是斜率优化的入门题
浅谈数形结合在信息学竞赛中的应用中讲得很好,这是其中的例二;
在此标记个人理解上觉得重要的地方;
首先这题求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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: