NC17059 队列Q

题目

题目描述

ZZT 创造了一个队列 Q。这个队列包含了 N 个元素,队列中的第 i 个元素用 \(Q_i\) 表示。Q1 表示队头元素,\(Q_N\) 表示队尾元素。队列中的元素是 N 的一个全排列。

ZZT 需要在这个队列上执行 P 次操作,操作分两种:
FIRST X: 将元素 X 移到队头。
LAST X: 将元素 X 移到队尾。

在 P 次操作之后,ZZT 想知道队列中的元素的排列方式,由于他最近很忙,因此需要请你帮他解决这个问题。

输入描述

第一行输入一个正整数 N,表示队列的大小。
第二行输入 N 个正整数,\(Q_1, Q_2, Q_3, ... ..., Q_N\)\(Q_i\) 表示队列中的第 i 个元素。保证这 N 个数是 N 的一个全排列。
第三行输入一个正整数 P,表示接下来要进行的操作次数。

接下来 P 行,第 i 行输入一个字符串 \(S_i\) 以及一个正整数 \(X_i\),表示一次操作。
\(1 ≤ N ≤ 10_5\).
\(1 ≤ Q_i ≤ N\).
\(1 ≤ P ≤ 10^5\).
\(S_i\in\) { “FIRST”, “LAST” }.
\(1 ≤ X_i ≤ 10^5\).

输出描述

输出 N 个正整数,表示 P 次操作之后的队列。

示例1

输入

4
4 2 1 3
3
FIRST 4
LAST 2
LAST 1

输出

4 3 2 1

题解

知识点:队列,STL。

如果是没操作过的原序列的元素,相对位置不会改变,而操作过的元素绝对不会出现在没操作过的元素中间,因为每次都是往队列两端插入,不可能到中间。

一个元素的最终位置,取决于最后一次操作的时间和操作方式,因为最后一次操作产生的位置不会被之前所有操作以及其他元素除了最后一次操作之外的操作影响。并且最后操作时间早的元素先确定位置。

因此保存每个时间操作的元素 \(xi\) 和方式 \(opi\) 以及每个元素最后的操作时间 \(vis\) 。从小到大遍历时间 \(i\) ,若 \(vis[xi[i]] = i\) ,即这个时间就是这个元素最后操作的时间,根据操作 \(opi[i]\) ,结合 \(deque\) 进行操作,最后输出即可。

时间复杂度 \(O(n+p)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>

using namespace std;

int a[100007];
int vis[100007], xi[100007], opi[100007];
deque<int> dq;

///元素位置由最后一次操作决定
int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    for (int i = 0;i < n;i++) cin >> a[i];
    int p;
    cin >> p;
    for (int i = 1;i <= p;i++) {
        string op;
        int x;
        cin >> op >> x;
        vis[x] = i;
        xi[i] = x;
        opi[i] = op == "FIRST";
    }

    for (int i = 0;i < n;i++) {
        if (!vis[a[i]]) dq.push_back(a[i]);
    }

    for (int i = 1;i <= p;i++) {
        if (vis[xi[i]] == i) {
            if (opi[i]) dq.push_front(xi[i]);
            else dq.push_back(xi[i]);
        }
    }
    for (int i = 0;i < n;i++) cout << dq[i] << ' ';
    cout << '\n';
    return 0;
}
posted @ 2022-07-02 16:58  空白菌  阅读(26)  评论(0编辑  收藏  举报