#797. 徐老师的超能力(经典模拟题)


一,50分

不用说,直接上代码:

#include <bits/stdc++.h>
using namespace std;
long long mei,x,y,op,tim,n,now,m[10000001];
int main()
{
  scanf("%lld",&n);//n次操作
  for(int i = 0; i < n; i++)
  {
    scanf("%lld",&op);//本次操作是哪一种
    if(op == 1)//第一种
    {
      scanf("%lld%lld",&x,&y);
      now += x;//现在的时间段+跨越x的时间
      mei += y;//吃掉一个美味度为y的羊腿
      m[now] = mei;//m[i]代表时间段为i的美味度
    }
    else
    {
      cin>>x;
      for(int j = now - x; j >= 0; j--)//通过枚举找到最后一个<= x - y 的吃完羊腿的时间点
        if(m[j] != 0 || j == 0)//如果不存在这样的时间点,则回到时间点0
        {
          tim = j;
          break;
        }
      mei = m[tim];
    }
    printf("%lld\n",mei);
  }
  return 0;
}

 

原因:在这里 ,而m[]数组的下标就是目前

,而如果把m数组开成10^18会爆空间,所以这种方法不行。 


二,100分

考虑记录两个数组 time[] num[] 分别表示i 件事情结束后的 时间和总美味度。 显然操作 1 可以直接加入,num 做一个前缀和即可;操2 只需二分答案找到最近的在需要 的时间之前的时间点即可,时间复杂度 O(n log n)。 但是此题也可以进一步优化。考虑每次回退操作直接从后往前依次模拟当前时间是否在需要的 时间之前,可以发现每一个事件最多进栈一次出栈一次,时间复杂度 O(n)

代码:
#include <bits/stdc++.h>
using namespace std;
long long ti[2000010],sum[2000010],m,now,op, x, y;
int main()
{
  cin>>m;
  for(int i = 1; i <= m; i++)
  {
    scanf("%lld%lld",&op,&x);
    if(op == 1)
    {
      scanf("%lld",&y);
      now++;
      ti[now] = ti[now - 1] + x;//前缀和
      sum[now] = sum[now - 1] + y;
    }
    else
    {
      int t = ti[now];
      if(ti[now] <= x) now = 0;
      else
        while(ti[now] > t - x)//二分答案
          now--;
    }
    cout<<sum[now]<<endl;
  }
  return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值