AcWing 3321. ATM队列

N 个人(编号 1∼N),排成一队在 ATM 机前准备取钱。

初始时,队列按编号升序的顺序排列。

第 i个人需要取 Ai 元钱。

一个人一次最多可以取 X元钱。

当轮到某个人取钱时,如果其需要的钱的数量大于 X,则只能先取 X 元钱,然后去队尾重新排队,等待下次轮到他取钱时,继续去取。

当一个人取够钱时,他就会拿着钱离开队列。

现在,请你确定所有人离开队列的顺序。

输入格式

第一行包含整数 T,表示共有 T 组测试数据。

每组数据第一行包含两个整数 N 和 X。

第二行包含 N 个整数 Ai。

输出格式

每组数据输出一个结果,每个结果占一行。

结果表示为 Case #x: y,其中 x 为组别编号(从 11 开始),y 是空格隔开的 N 个整数,表示所有人离开队列的顺序列表。

数据范围

60%60% 数据满足,1≤T≤100,1≤N≤100,
另外 40%40% 数据满足,1≤T≤10,1≤N≤105,
100%100% 数据满足,1≤Ai≤109,1≤X≤109。

输入样例:
2
3 3
2 7 4
5 6
9 10 4 7 2
输出样例:
Case #1: 1 3 2
Case #2: 3 5 1 2 4
样例解释

对于测试数据 1,共 3个人,单轮最大取钱数量为 3。

取钱过程如下:

  1. 初始时,队列为 [1,2,3],第一个人需要 2 元钱,取完离队。
  2. 此时,队列为 [2,3],第二个人需要 7 元钱,所以先取 3元,然后去队尾继续排队。
  3. 此时,队列为 [3,2],第三个人需要 4 元钱,所以先取 3 元,然后去队尾继续排队。
  4. 此时,队列为 [2,3],第二个人需要 4 元钱,所以先取 3 元,然后去队尾继续排队。
  5. 此时,队列为 [3,2],第三个人需要 1 元钱,取完离队。
  6. 此时,队列为 [2],第二个人需要 1 元钱,取完离队。
  7. 队列为空。

离队顺序为 [1,3,2]。

对于测试数据 2,共 5 个人,单轮最大取钱数量为 6。

取钱过程如下:

  1. 初始时,队列为 [1,2,3,4,5],第一个人需要 9 元钱,所以先取 6 元,然后去队尾继续排队。
  2. 此时,队列为 [2,3,4,5,1],第二个人需要 10 元钱,所以先取6 元,然后去队尾继续排队。
  3. 此时,队列为 [3,4,5,1,2],第三个人需要 4元钱,取完离队。
  4. 此时,队列为 [4,5,1,2],第四个人需要 7 元钱,所以先取 6 元,然后去队尾继续排队。
  5. 此时,队列为 [5,1,2,4],第五个人需要2 元钱,取完离队。
  6. 此时,队列为 [1,2,4],这三个人还需取得的钱数均不超过 6 元,所以可以顺次取完离队。

离队顺序为 [3,5,1,2,4]。

思路

首先看数据范围

最多共有109个人,最多有105数据

所以最多有1014规模的数据

要将算法时间复杂度控制在O(nlogn)

首先可以将每个所取得钱与最多能取得钱上取整

如果得到的数相同,那么根据他入队的顺序排序

算法

双指针排序

可以用pair来存

注意:n/m上取整可以用(n+m-1)/m实现

代码
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N=100010;

typedef pair<int,int> PII;

PII q[N];
#define x first
#define y second
int n,m;

int main()
{
    int T;
    cin>>T;
    for(int cases=1;cases<=T;cases++)
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            int a;
            cin>>a;
            q[i]={(a+m-1)/m,i};
        }
        sort(q+1,q+n+1);
        cout<<"Case #"<<cases<<": ";
        for(int i=1;i<=n;i++) cout<<q[i].y<<' ';
        puts("");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值