#优先队列 #贪心
## 思路
既然每次都是坐在最值上面,那么我们就可以定义两个优先队列,分别存上内向者和外向者的座位信息,需要的时候就可以 `top` 出来最大或最小的座位。
由于堆顶的值 `top` 出来实际上是座位的宽度,因此通过所有的 $w_i$ 都不相同的特性,我们可以使用 [[map]] 或者 `unordered_map` 来存储位置编号。
**优先队列介绍:**[Oi - Wiki](https://oi-wiki.org/lang/csl/container-adapter/#%E4%BC%98%E5%85%88%E9%98%9F%E5%88%97),[Cppreference](https://en.cppreference.com/w/cpp/container/priority_queue),本质上就是一个堆。
## 代码
```cpp
#include <iostream>
#include <queue> // 优先队列
#include <unordered_map> // 哈希表
using namespace std;
int n, v;
char c;
priority_queue<int, vector<int>, greater<int>> q1; // 小根堆,存储内向者
priority_queue<int, vector<int>, less<int>> q2; // 小根堆,存储内向者
unordered_map<int, int> f; // 哈希表
int main() {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> v;
f[v] = i, q1.push(v); // 存储进小根堆以及哈希表
}
for (int i = 1; i <= n << 1; ++i) {
cin >> c;
if (c == '0') { // 内向者
cout << f[q1.top()] << ' '; // 输出堆鼎的编号
q2.push(q1.top()), q1.pop(); // 这个位置只能坐外向者了
} else { // 外向者
cout << f[q2.top()] << ' ';
q2.pop(); // 这个位置满了
}
}
return 0;
}
```
## 思路 2
我们可以想,内向者既然选了一个最小的位置,那么最后一个内向者必然坐着有人当中最大的位置,然后外向者正好需要选择有人当中最大的位置,那不就是单调栈吗?
**单调栈介绍:**[Oi - Wiki]([单调栈 - OI Wiki (oi-wiki.org)](https://oi-wiki.org/ds/monotonous-stack/)),本质上就是满足一定顺序的栈。
## 代码
```cpp
#include <iostream>
#include <algorithm> // sort
#include <stack> // 栈
#include <unordered_map> // 哈希表
using namespace std;
const int kMaxN = 2e5 + 1;
int a[kMaxN], n, p;
char c;
stack<int> s;
unordered_map<int, int> f;
int main() {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i], f[a[i]] = i; // 读入并存进哈希表
}
sort(a + 1, a + n + 1); // 按座位宽度排序
for (int i = 1; i <= n << 1; ++i) {
cin >> c;
if (c == '0') {
cout << f[a[++p]] << ' '; // 选择下一个座位
s.push(a[p]); // 这个座位坐了内向者
} else {
cout << f[s.top()] << ' '; // 输出栈顶元素
s.pop(); // 出栈
}
}
return 0;
}
```