HDU 2993 MAX Average Problem (数形结合) #by Plato

来源:互联网 发布:基金技术分析软件 编辑:程序博客网 时间:2024/04/29 17:34

http://acm.hdu.edu.cn/showproblem.php?pid=2993

题意:给你一段长度为n的数列, 求其长度不小于 K 的平均值最大的子串。

解析参考:http://blog.ac521.org/?p=565

大意是先将问题转化为求斜率的问题,然后将朴素的N^2的算法用下凸曲线维护(要推导一些性质),降为2N的复杂度

数形结合

#include <cstdio>#include <iostream>#include <fstream>#include <cstring>using namespace std;int N,K;int sum[100010];struct point{    double x,y;};void read(int & a){    char ch;    while (ch = getchar(),ch < '0' || ch > '9');    a = ch - '0';    while (ch = getchar(),ch >= '0' && ch <= '9')        a = a*10 + ch - '0';}double solve(){    double maxx = 0;    static point s[100010];    int head = 1,tail = 0;    for (int j = K; j <= N; j++)    {        int k = j - K;        while (tail-1 >= head &&  (s[tail].x - s[tail-1].x)*(sum[k] - s[tail].y) - (s[tail].y - s[tail-1].y)*(k - s[tail].x)<0)//if (tail-1 >= head)        {                tail --;        }        s[++tail].x = k;        s[tail].y = sum[k];        while (head+1 <= tail && (sum[j] - s[head].y)/(j - s[head].x) < (sum[j] - s[head+1].y)/(j - s[head+1].x))            head++;        double temp = (double)(sum[j] - s[head].y)/(j - s[head].x);        //cout<<temp<<endl;        if (temp > maxx) maxx = temp;    }    return maxx;}int main(){    freopen("test.txt","r",stdin);    while(~scanf("%d%d",&N,&K))    {        sum[0] = 0;        for (int i = 1; i <= N; i++)        {            read(sum[i]);            sum[i] += sum[i-1];        }        printf("%.2lf\n",solve());    }    return 0;}