题目分析
根据题意,每趟在N个数字中遍历,最终选择框内会保留M个数字,这M个数字中一定是本次遍历中能取到的最大的M个数字。
设这M数字中的最大值为r_MAX,最小值为r_MIN。则任意数t可以根据以下规则分类:
-
index(t) <= index(r_MIN) 一定会被输出
-
index(r_MIN)<index(t)<=index(r_MAX)
a. t>r_MIN 则t属于M个数字中的一个,本轮输出 b. t<r_MIN 则t 属于下一轮遍历
-
index(t)>index(r_MAX) ,此时所需要取的M个数字已经取满,等待下一轮遍历。
综合上面的分类:
每轮输出的数字一定是该轮中最大的M个数字,该轮M个数字中最小的数字前面的所有数字。
以上分析实践后,发现有问题,代码采用模拟方式
代码
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int A = 100010;
int NUM[A];
int main()
{
int N, M;
vector<int> current, next;
priority_queue<int, vector<int>, greater<int>> q;
scanf("%d %d", &N, &M);
for (int i = 0; i < N; i++) {
scanf("%d", &NUM[i]);
}
int index = 0, count = 0,last;
for (; index < M; index++) q.push(NUM[index]);
while (count != N) {
last = q.top();
current.push_back(last);
q.pop();
count++;
if (index < N) {
if (last < NUM[index]) {
q.push(NUM[index++]);
}
else {
next.push_back(NUM[index++]);
}
}
if (q.empty()) {
//输出当前
for (int i = 0; i < current.size(); i++) {
if (i != 0)printf(" ");
printf("%d", current[i]);
}
printf("\n");
current.clear();
//
for (int i = 0; i < next.size(); i++) {
q.push(next[i]);
}
next.clear();
}
}
}```