查看: 1435|回復: 0
打印 上一主題 下一主題

[HOJ] 302 - 最大平均值

[複製鏈接]
  • TA的每日心情
    慵懶
    2015-4-10 14:18
  • 簽到天數: 78 天

    [LV.6]常住居民II

    176

    主題

    612

    帖子

    3959

    積分

    管理員

    Rank: 9Rank: 9Rank: 9

    積分
    3959

    台南一中資訊社新手達陣程式設計達人 - 2014

    跳轉到指定樓層
    樓主
    發表於 2014-5-19 22:30:28 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

    趕快加入我們來參與討論吧!

    您需要 登錄 才可以下載或查看,沒有帳號?加入我們

    x
    原題:http://hoj.twbbs.org/judge/problem/view/302
    AC:http://hoj.twbbs.org/judge/judge/submission/17485

    大家都做O(nlogn)的,我偏要做O(n)的斜率優化,作法參考這中國國家代表隊論文 (HOJ),基本上是做了「數形」結合的概念轉化為一斜率極值問題來做。

    #ifdef DBG
  • #include<conio.h>
  • #define pause() getch()
  • #else
  • #define pause()
  • #endif
  • #include<cstdio>
  • #include<iostream>
  • #include<deque>
  • #include<algorithm>
  • using namespace std;
  • typedef long long ll;
  • typedef pair<ll,ll> pii;
  • #define mp(X,Y) make_pair((X),(Y))
  • ll sum[100001]={0};;
  • int N,F;
  • deque<pii> dq;

  • inline int cross(pii a,pii b,pii c)
  • {
  •         return (b.first-a.first)*(c.second-b.second)-(b.second-a.second)*(c.first-b.first);
  • }

  • void push(pii p)
  • {
  •         while(dq.size()>1)
  •         {
  •                 pii &m=dq[0];
  •                 pii &b=dq[1];
  •                 if(cross(b,m,p)<=0)
  •                         dq.pop_front();
  •                 else
  •                         break;
  •         }
  •         dq.push_front(p);
  • }

  • bool next_is_better(pii pt)
  • {
  •         pii &b=dq.back();
  •         pii &b2=*(dq.rbegin()+1);
  •         //double k1=(double)(pt.second-b.second)/(pt.first-b.first);
  •         //double k2=(double)(pt.second-b2.second)/(pt.first-b2.first);
  •         return (pt.second-b.second)*(pt.first-b2.first)<(pt.second-b2.second)*(pt.first-b.first);
  •         //return k1<k2;
  •        
  • }

  • int main()
  • {
  •         ll ans=0;
  •         scanf("%d%d",&N,&F);
  •         for(int i=1;i<=N;++i)
  •         {
  •                 scanf("%lld",&sum[i]);
  •                 sum[i]=sum[i-1]+sum[i]*1000;
  •         }
  •         for(int i=F;i<=N;++i)
  •         {
  •                 push(mp(i-F,sum[i-F]));
  •                 while(dq.size()>1&&next_is_better(mp(i,sum[i])))dq.pop_back();
  •                 ans=max(ans,(dq.back().second-sum[i])/(dq.back().first-i));
  •         }
  •         printf("%lld\n",ans);
  •        
  •         return 0;
  • }



  • 回復

    使用道具 檢舉

    您需要登錄後才可以回帖 登入 | 加入我們

    本版積分規則

    快速回覆 返回頂部 返回列表