a tutorial on computer science

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  21 随笔 :: 0 文章 :: 17 评论 :: 0 Trackbacks
        题目的意思很简单,给出N个正整数,求最大的,长度大于K的某一段的平均值。好吧,这句听起来有点拗口。数学表达式就是 Max(ave(i,j))   (j-i>=K)。
       这题是去年百度之星第二场比赛的一道题,煞费苦心不会做,那时候看了论文也不会做。过了快一年了,今天终于把它A掉了。。。
      
       首先,ave(i,j)可以变形为一个式子, ave(i,j) = (sum[j] - sum[i-1]  ) / (j - i + 1) 。
       这个式子要表达什么意思呢?表示j点到i点得斜率!如此神奇的想法。。。
      变成斜率之后,问题远远没有得到解决。问题变成了给出N个点的坐标,求这N个点任意连线的最大斜率。最普通的办法:从前到后枚举N个点,再枚举前0到i-k个点,比较的出最大斜率。但是通过作图我们可以得出一个结论,对于三个点,a,b,c,如果ca的斜率比cb的大,那么以后任意一个点,到点b的斜率都不可能比到a和c的大。所以这时候要舍弃掉b点。所以在维护前面0,i-K个点得时候,如果出现了上述提到的情况,则删除点b,好了,这样复杂度最坏情况下还是N^2。我们继续想,当出现一个新的点得时候,真的要枚举前面所有的点吗?我们只要找到维护的点到当前点得切线就好了,这个可以用二分查找找出来,比较麻烦。最后一步神优化:当当前维护的点得前面的点不是最大斜率的时候,以后的点也不可能是最大斜率。这个自己证明去吧~
     这个题煞费苦心的想了一天,明白怎么回事了,发现结论很简单。但是交到hdoj上的时候,TLE了。没耐心看了discuss,原来是scanf要自己写。不想写,百度代码,发现有个神人写了五十行的代码,未自己写输入,交,A之。原来是自己的代码太冗余了。于是便仿照他的写法,发现问题很简单,一切很明了~A之。代码如下:
//by bigrabbit

#include 
<stdio.h>

typedef 
struct
{
  
int x,y;
}
node;
node queue[
100010],tmp;
int head,tail;

double res;

int N,K,sum[100010];

double max(double a,double b)
{
    
if(a > b)
      
return a;
    
return b;
}


long long xmul(node a,node b,node c)
{
   
return (long long)(c.y-a.y)*(b.x-a.x) - (long long)(b.y - a.y)*(c.x - a.x) ;
}


int main()
{
    
int i;
   
while(scanf("%d%d",&N,&K)!=EOF)   
   
{
     sum[
0= 0;
     
for(i=1;i<=N;i++)
     
{
        scanf(
"%d",&sum[i]);
        sum[i] 
+= sum[i-1];
     }

  
     head 
= tail = 0;
     res 
= 0.0;
    
     
for(i=K;i<=N;i++)
     
{
        tmp.x 
= i-K;
        tmp.y 
= sum[i-K];
        
while(head - tail >= 2 && xmul(queue[head-2],queue[head-1],tmp) <= 0 ) 
         head
--;
        queue[head
++= tmp;
        
         node now;
        now.x 
= i;now.y = sum[i];
        
while(head - tail >= 2 && xmul(queue[tail],queue[tail+1],now) >= 0 )  
          tail
++;
   
        res 
= max(res,(double)(sum[i] - queue[tail].y)/(double)(i - queue[tail].x));
     }

    printf(
"%.2f\n",res);
   }

   
return 0;
}

posted on 2012-03-08 16:27 bigrabbit 阅读(1000) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理