codeforces 948C / 923B Producing Snow 【优先队列+思维】

7 篇文章 0 订阅
0 篇文章 0 订阅

戳我 传送至 Producing Snow
戳我 到参考网站

**题意:**每天产生一堆雪,大小为v[i]个单位体积,然后每天对应一个数值a[i]代表当天温度,然后剩下的每一堆的雪都会减少这个温度的数值,小于等于0就不会再减少,问总共减少来的多少单位的雪

**思路:**用一个优先队列,从小到大检视单位体积最小的那一堆雪,并且运用了前缀和
压队列压的是 第i天产生雪的体积+前一天积累的温度和 ,如果遇到当天积累的温度和大于这个数值,就出队列,意思是已经融化掉了
为什么压队列是这个公式?是因为在第k天,对于第p堆的雪(k>=p),que.top()和sum[k]比较的话实际就是v[p]和a[p]+…+a[k]比较,使得前第p-1天的温度不会影响第p天的雪
最后ans+=que.size()*a[i]表示的是如果存在某些堆的雪没有消融掉,那么这些雪都会融掉a[i]个单位体积,这个值是答案的一部分

贴一发大牛的AC码

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
long long cnt,a[100005],t,ans=0,sum[100005]={0},tmp,v[100005];
int main()
{
    long long n,i,j;
    while(~scanf("%I64d",&n))
    {
        memset(sum,0,sizeof(sum));
        memset(a,0,sizeof(a));
        priority_queue<long long,vector<long long >,greater<long long> > que;
       // 优先队列,从小到大
        for(i=1;i<=n;i++) scanf("%I64d",&v[i]);
        for(i=1;i<=n;i++)
        {
            scanf("%I64d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        for(i=1;i<=n;i++)
        {
            ans=0;
            que.push(v[i]+sum[i-1]);
            while(!que.empty()&&que.top()<=sum[i])
            {
                ans+=que.top()-sum[i-1];
                que.pop();
            }
            ans+=que.size()*a[i];
            if(i==n) printf("%I64d\n",ans);
            else printf("%I64d ",ans);
        }
    }
    return 0;
}

对比一下自己TLE的代码:

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
    long long n,i,j;
    while(~scanf("%I64d",&n))
    {
        long long cnt,a,b,t,ans=0,tmp,v[100005];
        queue<long long> que;
        for(i=0;i<n;i++)
        {
            scanf("%I64d",&v[i]);
        }
        for(i=0;i<n;i++)
        {
            ans=0;
            que.push(v[i]);
            scanf("%I64d",&t);
            cnt=que.size();
            for(j=0;j<cnt;j++)
            {
                a=que.front();
                que.pop();
                if(a>=t)
                {
                    b=a-t;
                    ans+=t;
                    que.push(b);
                }
                else ans+=a;
            }
            if(i==n-1) printf("%I64d\n",ans);
            else printf("%I64d ",ans);
        }
    }
    return 0;
}

TLE代码思路:
朴素地模拟吧,压入当天的雪,然后看剩下有多少堆(que.size())
然后 j 循环 que.size() 次,每次取出队列头的雪,还没融化完的,减完之后继续压入队列,融化完的就不压入。答案应该是正确的。

反思 和 与AC代码的对比:
虽然是运用了队列,但是还是没有充分发挥队列的作用,而且操作比较繁杂。
TLE代码的思路和操作是不断地减,这样如果遇到雪的单位体积很大,但是温度又很低,就会TLE。
AC代码则没有进行过多的减和入队列,只是判断何时雪全部融化掉就出队列,然后ans增加,对于没有出队列的,ans就加上剩下雪的堆数*当天温度

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值