• HDU 2993 MAX Average Problem (斜率DP)


    MAX Average Problem

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4416    Accepted Submission(s): 1106

    Problem Description
    Consider a simple sequence which only contains positive integers as a1, a2 ... an, and a number k. Define ave(i,j) as the average value of the sub sequence ai ... aj, i<=j. Let’s calculate max(ave(i,j)), 1<=i<=j-k+1<=n.
     
    Input
    There multiple test cases in the input, each test case contains two lines. The first line has two integers, N and k (k<=N<=10^5). The second line has N integers, a1, a2 ... an. All numbers are ranged in [1, 2000].
     
    Output
    For every test case, output one single line contains a real number, which is mentioned in the description, accurate to 0.01.
     
    Sample Input
    10 6
    6 4 2 10 3 8 5 9 4 1
     
    Sample Output
    6.50
     
    Source
     
    Recommend
    chenrui
     
     
     
     

    这个也是论文上的例题,给你一个正数序列,注意全是正数,否则就不满足和的单调性了,关于这个结论某些部分就不能在运用了,我先说一下前提条件,我就是前提条件没搞请,才弄的模模糊糊的,弄清楚前提条件后就会发现其实不是很难的。

    前提条件:

    1.所有的数均是(保证了他们的和是单调递增的)

    2.求的是连续的序列,且序列的长度大于等于k

    3.求的是序列的最大平均值,也就是(i, sum[i])值中斜率最大的那个值

    解体思路:

    现在我只是干讲,如果感觉不形象的话,可以参考那篇著名的论文。

    由于我们是要求斜率最大值,如果枚举的话,我们肯定是把当前的点与它前面的所有的点求斜率,取最大值。

    现在我们想降低复杂度,我们可以从两个方面入手,

    1,去掉每个位置前面的那些在后来的枚举中不可能产生最优解的点

    2,快速的去定位最优解

    首先讲第一个:

    1.如何减少不必要的枚举呢?

    我们假设存在三个点,i,j, k三个点构成的是上凸包,现在我们沿着j,k作延长线,如何后来的点在延长线的下方,那么该后来的点是不能构成最优解的,因为当前延长线的解已经比后来的点构成的所有的点优或则说与i构成的直线的斜率一定比与j构成的斜率大,如果后来的点在延长线的上方,那么你会发现与k构成的斜率肯定比与j构成的斜率大,那么问题就出现了,j不可能在后来的更新中形成最优解,那么就可以将其删除,这样在后来的枚举中少了它了。很神奇的证明,不过的确特别的有用。

    2.如何更快的去定位最优解呢?

    一般的做法就是二分,不过这里的做法很绝,把原来O(NlgN)的做法优化到了,O(N)

    还是把不可能构成最优解的删掉,(注意sum[i]是单调递增的),如果当前构不成最优解,那么在后来的点着中是不可能构成最优解的,因此可以删掉,到底为什么,还是自己看自己想。这里维持最小长度为k还是很巧秒的,不过HDU交C++可过,交G++TLE,据说只要有C++那么它的服务器系统肯定是windows,那么交G++调用MingW肯定会慢的。

     

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 
     5 using namespace std;
     6 
     7 const int maxn=100010;
     8 
     9 double sum[maxn];
    10 int q[maxn];
    11 
    12 double cross(int i,int j,int k){
    13     double tmp;
    14     tmp=(k-i)*(sum[j]-sum[i])-(j-i)*(sum[k]-sum[i]);
    15     return tmp;
    16 }
    17 
    18 double max(double a,double b){
    19     return a>b?a:b;
    20 }
    21 
    22 int Input(){
    23     char c;
    24     int ans;
    25     while(c=getchar(),c<'0' || c>'9') ;
    26     ans=c-'0';
    27     while(c=getchar(),c>='0' && c<='9')
    28         ans=ans*10+c-'0';
    29     return ans;
    30 }
    31 
    32 double f(int i,int k){
    33     i=q[i];
    34     return (sum[k]-sum[i])/(k-i);
    35 }
    36 
    37 int main(){
    38 
    39     //freopen("input.txt","r",stdin);
    40 
    41     int n,k;
    42     while(~scanf("%d%d",&n,&k)){
    43         sum[0]=0;
    44         int i,j;
    45         for(i=1;i<=n;i++)
    46             sum[i]=sum[i-1]+Input();
    47         int head=0,rear=0;
    48         double ans=0;
    49         for(i=k;i<=n;i++){
    50             j=i-k;
    51             while(head<rear && cross(q[rear-1],q[rear],j)>=0)
    52                 rear--;
    53             q[++rear]=j;
    54             while(head<rear && f(head+1,i)>=f(head,i))
    55                 head++;
    56             ans=max(ans,f(head,i));
    57         }
    58         printf("%.2lf\n",ans);
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    Python2.7-zlib
    Python2.7-sqlite3
    Python2.7-dbm、gdbm、dbhash、bsddb、dumbdb
    Python2.7-anydbm
    Python2.7-marshal
    Python2.7-shelve
    Python2.7-copy_reg
    Python2.7-pickle, cpickle
    Python2.7-shutil
    Python2.7-fnmacth
  • 原文地址:https://www.cnblogs.com/jackge/p/3026219.html
Copyright © 2020-2023  润新知