在线评测链接
题目描述
塔子哥将对 1 0 5 10^5 105 个通道下发任务。
当用户输入 − 1 -1 −1 时,分配没有任务且编号最小的通道给用户。当用户输入有效的通道编号时,回收并清空此通道。
请你计算出若干次操作后,下一次用户申请时将得到的通道编号,若无可以使用的通道,返回 − 1 -1 −1。
输入格式
第一行为一个整数 n n n,表示用户输入次数。
接下来一行 n n n 个整数,分别表示每一次操作用户的输入数,通道编号在 0 0 0 到 50000 50000 50000 内。
1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1≤n≤105
输出格式
输出下一次将申请到的通道编号,若无可使用的通道,输出 − 1 -1 −1。
7
-1 -1 1 -1 0 -1 2
2
思路:模拟/小根堆
我们可以使用队列来模拟这个问题,首先把 1 0 5 10^5 105个通道编号全部按顺序入队(通道编号下标从0开始),这样队头元素就是编号最小的通道
- 用户输出-1,直接弹出队头元素
- 用户输出为 x x x,则使用二分查找,找到第一个 ≥ x \ge x ≥x的位置,将该位置插入元素 x x x
最终输出的结果即为队列的队头元素
上述模拟的过程,是使用队列+二分查找的思想,也可以直接使用优先队列模拟(Java代码),优先队列是小根堆,这样堆顶就是编号最小的通道
时间复杂度
O ( n l o g n ) O(nlogn) O(nlogn)
代码
C++
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 40;
//[1, n],高度不超过 k
int cache[N][N];
int dfs(int n, int k)
{
if(cache[n][k] != -1) return cache[n][k];
if(k == 0 && n == 0) return 1;
if(k == 0 && n != 0) return 0;
if(n == 0) return 1;
int res = 0;
for(int i = 1; i <= n; ++ i) {
res += dfs(i - 1, k - 1) * dfs(n - i, k - 1);
}
return cache[n][k] = res;
}
int main()
{
int n, k;
cin >> n >> k;
memset(cache, -1, sizeof cache);
cout << dfs(n, k) << endl;
return 0;
}
python代码
import bisect
from collections import deque
n = int(input())
ops = [int(c) for c in input().split()]
q = deque([i for i in range(100000)])
for op in ops:
if op == -1:
q.popleft()
else:
# 插入op
bisect.insort(q, op)
if q: print(q[0])
else:
print(-1)
Java代码
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
PriorityQueue<Integer> q = new PriorityQueue<>();
for (int i = 0; i < 100000; ++i) {
q.offer(i);
}
for (int i = 0; i < n; ++i) {
int op = scanner.nextInt();
if (op == -1) {
q.poll();
} else {
q.offer(op);
}
}
if (!q.isEmpty()) {
System.out.println(q.peek());
} else {
System.out.println(-1);
}
}
}