zoukankan      html  css  js  c++  java
  • NOIp2016 蚯蚓 【二叉堆/答案单调性】By cellur925

    题目传送门

    $Sol$

    $50pts$:我们考虑$q==0$的情况,每次在所有的蚯蚓中找到一只长度最大的,这非常二叉堆。所以我们可以用一个优先队列,随便水一下就有50分。($NOIp$的分真这么好拿?)

    (理论得分60分,由于种种常数等的原因,实际会达到50分)

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<queue>
     4 
     5 using namespace std;
     6 
     7 int n,m,can,u,v,t;
     8 int tim[7000090];
     9 priority_queue<int>q;
    10 
    11 int main()
    12 {
    13     scanf("%d%d%d%d%d%d",&n,&m,&can,&u,&v,&t);
    14     if(can==0)
    15     {
    16         for(int i=1;i<=n;i++)
    17         {
    18             int x=0;
    19             scanf("%d",&x);q.push(x);
    20         }
    21         for(int i=1;i<=m;i++)
    22         {
    23             int tmp=q.top();q.pop();tim[i]=tmp;
    24             int a=u*tmp/v;int b=tmp-a;
    25             q.push(a);q.push(b);
    26         }
    27         for(int i=t;i<=m;i+=t)
    28             printf("%d ",tim[i]);
    29         printf("
    ");
    30         for(int i=1;i<=n+m;i++)
    31         {
    32             if(q.empty()) break;
    33             if(i%t==0) printf("%d ",q.top());
    34             q.pop();
    35         }
    36     }
    37     return 0;
    38 }
    50pts

    $85pts$:我们不得不考虑每次切蚯蚓后其他的蚯蚓长度情况(为了拿到更多的部分分),我们不妨考虑下线段树和分块中的思想。

    Chemist:线段树中最精妙的设计是什么?

    我:懒标记!

    Chemist:对!你就往这想。

    我们并不需要每次都把其他蚯蚓的长度增加,而是等需要他们的时候再增加。于是,我们同样在维护一个二叉堆(优先队列),但是这里面存的是还是最初的蚯蚓们长度。我们再维护一个增量即可。

    另外这道题是著名的卡常数代表,开始我80分是因为开了$longlong$,有位老哥和我打暴力的方法一样,然后它用$int+double$转化卡到了85分。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<queue>
     4 
     5 using namespace std;
     6 typedef long long ll;
     7 
     8 ll n,m,can,u,v,t;
     9 ll sigma;
    10 priority_queue<ll>q;
    11 
    12 void re(ll &x)
    13 {
    14     x=0;
    15     char ch=getchar();
    16     bool flag=false;
    17     while(ch<'0'||ch>'9') flag|=(ch=='-'),ch=getchar();
    18     while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    19     x=flag ? -x : x;
    20 }
    21 
    22 int main()
    23 {
    24     re(n),re(m),re(can),re(u),re(v),re(t);
    25     for(register int i=1;i<=n;i++)
    26     {
    27         ll x=0;
    28         re(x);q.push(x);
    29     }
    30     for(register int i=1;i<=m;i++)
    31     {
    32         ll tmp=q.top()+sigma;q.pop();//输出要把增量带上 
    33         if(i%t==0) printf("%lld ",tmp);
    34         ll a=1ll*u*tmp/v;ll b=tmp-a;
    35         a-=sigma;b-=sigma;//进优先队列的都是不带增量的 
    36         a-=can;b-=can;//为了防止以后被认为在这时刻增加了 现在先减去 
    37         q.push(a);q.push(b);
    38         sigma+=can;//继续维护增量 
    39     }
    40     printf("
    ");
    41     for(register int i=1;i<=n+m;i++)
    42     {
    43         if(q.empty()) break;
    44         if(i%t==0) printf("%lld ",q.top()+sigma);
    45         q.pop();
    46     }
    47     return 0;
    48 }
    85pts

    $100pts$:正解的思维难度还是有的,先被切掉的蚯蚓长度一定比后被切掉的蚯蚓长度大。

    (引用自@aiyougege,侵删)

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<queue>
     4 #include<cmath> 
     5 
     6 using namespace std;
     7 typedef long long ll;
     8 
     9 ll n,m,q,t,sigma;
    10 double u,v,p;
    11 ll qiuyin[100090];
    12 queue<ll>q1,q2,qq;
    13 
    14 bool cmp(ll a,ll b)
    15 {
    16     return a>b;
    17 }
    18 
    19 int main()
    20 {
    21     scanf("%lld%lld%lld%lf%lf%lld",&n,&m,&q,&u,&v,&t);
    22     p=u/v;
    23     for(int i=1;i<=n;i++) scanf("%lld",&qiuyin[i]);
    24     sort(qiuyin+1,qiuyin+1+n,cmp);
    25     for(int i=1;i<=n;i++) qq.push(qiuyin[i]);
    26     for(int i=1;i<=m;i++)
    27     {
    28         ll len=0,len1=0,len2=0;
    29         ll qwq=-1e16-7,qaq=-1e16-7,orz=-1e16-7;
    30         if(!q1.empty()) qwq=q1.front();
    31         if(!q2.empty()) qaq=q2.front();
    32         if(!qq.empty()) orz=qq.front();
    33         if(!q1.empty()&&qwq>=qaq&&qwq>=orz) q1.pop();
    34         else if(!q2.empty()&&qaq>=qwq&&qaq>=orz) q2.pop();
    35         else if(!qq.empty()&&orz>=qaq&&orz>=qwq) qq.pop();
    36         
    37         len=max(max(qwq,qaq),orz);len+=sigma;
    38         if(i%t==0) printf("%lld ",len);
    39         len1=floor(p*len)-q-sigma;
    40         len2=len-floor(p*len)-q-sigma;
    41         q1.push(len1),q2.push(len2);
    42         sigma+=q;
    43     }
    44     printf("
    ");
    45     for(int i=1;i<=n+m;i++)
    46     {
    47         ll len=0,qwq=-1e16-7,qaq=-1e16-7,orz=-1e16-7;
    48         if(!q1.empty()) qwq=q1.front();
    49         if(!q2.empty()) qaq=q2.front();
    50         if(!qq.empty()) orz=qq.front();
    51         if(!q1.empty()&&qwq>=qaq&&qwq>=orz) q1.pop();
    52         else if(!q2.empty()&&qaq>=qwq&&qaq>=orz) q2.pop();
    53         else if(!qq.empty()&&orz>=qaq&&orz>=qwq) qq.pop();
    54         len=max(max(qwq,qaq),orz)+sigma;
    55         if(i%t==0) printf("%lld ",len);
    56     }
    57     return 0;
    58 }
    View Code

    但是期间奥妙重重WA了无数次,也不知怎么肥事。重敲就活过来了,可能是精度问题的锅,还需要注意下。


    小结:NOIp的部分分还是给的很足的,有时还可能不小心敲成正解?第二题还是要重视,尽量多拿分。

  • 相关阅读:
    【贪心】时空定位I
    【贪心】删数问题
    【贪心】取火柴游戏
    【贪心】均分纸牌
    Fix a Tree
    Vacations
    One Bomb
    Abandoned country
    BZOJ 1006 [HNOI2008]神奇的国度
    BZOJ 2118 墨墨的等式
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9742247.html
Copyright © 2011-2022 走看看