CF982B Bus of Characters 题解

思路

既然每次都是坐在最值上面,那么我们就可以定义两个优先队列,分别存上内向者和外向者的座位信息,需要的时候就可以 top 出来最大或最小的座位。

由于堆顶的值 top 出来实际上是座位的宽度,因此通过所有的 \(w_i\) 都不相同的特性,我们可以使用 map 或者 unordered_map 来存储位置编号。

优先队列介绍:Oi - WikiCppreference,本质上就是一个堆。

代码

#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),本质上就是满足一定顺序的栈。

代码

#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;
}
posted @ 2023-10-15 14:35  haokee  阅读(26)  评论(0)    收藏  举报