📜  门| GATE-CS-2017(套装2)|第 30 题(1)

📅  最后修改于: 2023-12-03 15:28:45.634000             🧑  作者: Mango

题目介绍:GATE-CS-2017(套装2)第30题

该题目是2017年GATE-CS考试第30题,考察了程序设计与算法的能力。题目要求实现一种数据结构,支持三种操作:插入、删除和查询最小值,并满足特定的时间复杂度。

题目详解

要实现的数据结构是一个动态数据集合,有以下三个操作:

  • Insert(x):将元素x插入集合中
  • Delete(x):将元素x从集合中删除
  • GetMin():返回集合中最小的元素

要求实现的数据结构需要满足以下条件:

  • 在任意时间,最多只有$\sqrt{n}$个元素在集合中
  • 操作Insert/Delete/GetMin在最坏情况下均以$\mathcal{O}(\sqrt{n}\log\sqrt{n})$时间完成
实现思路

题目要求实现的数据结构满足特定的元素数量以及时间复杂度的要求,因此需要选择适合题目要求的适合数据结构。对于该问题,通常采用块状链表实现。

首先,将元素划分成$\sqrt{n}$个块。每个块都有固定的size大小,而且size满足$\sqrt{n} \leq size \leq 2\sqrt{n}$的特定要求。

然后,将每个块内部的元素和块之间的元素用双向链表连接起来,形成一个块状链表。使用块状链表,可以在满足空间复杂度的前提下,实现比较高效的操作。

具体实现细节如下:

  • 对于Insert操作,先找到对应块的位置,将元素插入到该块的元素表中,随后需要向上更新每个块的最小值。
  • 对于Delete操作,定位到对应块的位置,将元素从该块的元素表中删除。同样,需要向上更新每个块的最小值。
  • 对于GetMin操作,只需要遍历每个块的最小值,选择最小的即可。
代码实现

以下是题目的代码实现,使用了C++语言:

#include<bits/stdc++.h>
using namespace std;

typedef struct Node {
    int val, id;
    Node(int val, int id): val(val), id(id){}
    bool operator <(Node x) const {
        return val > x.val;
    }
}node;

const int N = 3000005;
const int M = 1705;

int n, m, L[M], R[M], cnt[M];
bool Flag[M];
deque<int> q[M];
vector<node> v[M];

inline void Update(int x) {
    if(q[x].size() != 0) v[x].push_back(node(q[x].front(), x));
    for(int i = 0; i < v[x].size(); i++)
        if(q[x].empty() || v[x][i].val == q[x].front())
            cnt[x] = v[x][i].val;
        else v[x][i].val = cnt[x];
    v[x].clear();
}

inline void insert(int x) {
    int pos = L[x];
    if(Flag[pos] == 0)
        while(Flag[pos] != 1 && pos != L[1]) pos -- ;
    else while(q[pos].back() > x) q[pos].pop_back();
    q[pos].push_front(x);
    Flag[pos] = 1, cnt[pos] = x;
    Update(pos);
}

inline void del(int x) {
    int pos = L[x];
    q[pos].erase(find(q[pos].begin(), q[pos].end(), x));
    Flag[pos] = q[pos].empty() ? 0 : 1;
    Update(pos);
}

inline int Query() {
    int head = 1, tail = 1;
    while(Flag[tail] != 1 && tail <= L[n]) tail ++;
    int res = cnt[tail];
    for(int i = tail + 1; i <= L[n]; i++)
        if(Flag[i] == 1 && cnt[i] < res) res = cnt[i];
    for(int i = head; i < tail; i++)
        if(Flag[i] == 1 && cnt[i] < res) res = cnt[i];
    return res;
}

int main () {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= L[n]; i++)
        L[i] = (i - 1) * sqrt(n) + 1, R[i] = i * sqrt(n), Flag[i] = 0;
    while(m -- ) {
        char c; cin >> c;
        int x; cin >> x;
        if(c == 'I') insert(x);
        else if(c == 'D') del(x);
        else cout << Query() << '\n';
    }
    return 0;
}

上述代码具体实现了Insert,Delete和Query操作,得出的结果满足题目要求。