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,2,3],第一个人需要 2 元钱,取完离队。
- 此时,队列为 [2,3],第二个人需要 7 元钱,所以先取 3元,然后去队尾继续排队。
- 此时,队列为 [3,2],第三个人需要 4 元钱,所以先取 3 元,然后去队尾继续排队。
- 此时,队列为 [2,3],第二个人需要 4 元钱,所以先取 3 元,然后去队尾继续排队。
- 此时,队列为 [3,2],第三个人需要 1 元钱,取完离队。
- 此时,队列为 [2],第二个人需要 1 元钱,取完离队。
- 队列为空。
离队顺序为 [1,3,2]。
对于测试数据 2,共 5 个人,单轮最大取钱数量为 6。
取钱过程如下:
- 初始时,队列为 [1,2,3,4,5],第一个人需要 9 元钱,所以先取 6 元,然后去队尾继续排队。
- 此时,队列为 [2,3,4,5,1],第二个人需要 10 元钱,所以先取6 元,然后去队尾继续排队。
- 此时,队列为 [3,4,5,1,2],第三个人需要 4元钱,取完离队。
- 此时,队列为 [4,5,1,2],第四个人需要 7 元钱,所以先取 6 元,然后去队尾继续排队。
- 此时,队列为 [5,1,2,4],第五个人需要2 元钱,取完离队。
- 此时,队列为 [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;
}