题目描述
从左往右有无限多张凳子,凳子的编号从左往右依次是:1,2,3,4,5,6……。有 N 只奶牛排着队正走过来,
N 只奶牛的编号分别用1,2,3,4,… N 来表示。它们要找合适的凳子坐。每只奶牛选择凳子的规则都是:
- 奶牛都不喜欢太拥挤,于是奶牛选择的凳子左边
D 距离内不能有其它奶牛坐,右边 D 距离内也不能有奶牛坐。比如:两头奶牛,当D =10时,一只奶牛选择编号是47的凳子,另一只选择编号是57的凳子,这是合法的。当 D =10时,一只奶牛选择编号是47的凳子,另一只选择编号是56的凳子,这是不合法的,因为他们之间的距离小于10。- 对于第
i 只奶牛来说,它选择的凳子的编号必须大于或等于 Ai。
- 在满足第(1)、第(2)点的前提下,奶牛会尽量选择编号小的凳子坐下来。
现在这 N 只奶牛按照编号从小到大的顺序排好了队,编号是1的奶牛排在最前面,它首先按照如上的规则选好凳子后就坐下来,接着是编号是2的奶牛选择凳子后坐下来,接着是编号是3的奶牛选择凳子后坐下来 ,……最后选择凳子的奶牛是第
N 只奶牛。
你的任务是:输出编号是1至 N 的奶牛,它们各自选择的凳子的编号。
输入格式 1043.in
多组测试数据。
第一行,一个整数R ,表示有 R 组测试数据。1≤R≤6 。
每组测试数据格式如下:
第一行,两个正整数,N 和D 。 1≤N≤1000。 1≤D≤106。
第二行,N 个整数,第i 个整数表示 Ai。 1≤Ai≤106。
输出格式 1043.out
共 R 行,每行对应一组测试数据。
每组测试数据的输出都是一行,该行包含N 个整数,空格分开,第 i 个整数表示第i 只奶牛选择的凳子的编号。
输入样例 1043.in
5
4 10
1 21 11 7
4 11
1 21 11 7
4 1000000
1000000 1000000 1000000 1
4 999999
1000000 1000000 1000000 1
4 1
8 7 5 1
输出样例 1043.out
1 21 11 31
1 21 32 43
1000000 2000000 3000000 4000000
1000000 1999999 2999998 1
8 7 5 1
最近做多了线段树的题,第一反应就是写个线段树维护一下凳子被占用的情况,似乎是可行的,只是没有注意到数据范围。而且有无限多张椅子,理论上是不可能在真正意义上实现的。样例在本地过了,一提交却 MLE 。
于是又想起 lws 的最高指示:“数据量决定算法。”发现牛的数量其实是很少的,可以从这一点入手。
也就是说,对于每一头牛,都可以将其与之前已经安排好位置的牛进行对比,从而选出合适的位置。但在对比时要注意,之前的奶牛要按顺序排好,否则可能会出现为了满足后面的奶牛但却与前面的奶牛冲突的情况。因此每确定一头奶牛的位置都重新排一次序,总的时间复杂度为 O(n2log2n)。
参考代码:
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 1e6 + 10;
int a[maxn], b[maxn];
int main(void) {
freopen("1043.in", "r", stdin);
freopen("1043.out", "w", stdout);
int r;
scanf("%d", &r);
while (r--) {
int n, d;
scanf("%d%d", &n, &d);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
for (int i = 0; i < n; i++) {
b[i] = a[i];
for (int j = 0; j < i; j++)
if (abs(b[i] - b[j]) < d) b[i] = b[j] + d;
printf("%d ", b[i]);
sort(b, b + i + 1);
}
putchar('\n');
}
return 0;
}