On this page
article
Priority Queue DS
Sobre
Mantem updates aplicados em uma estrutura de dados
que permita rollback e nao seja amortizada.
Cada update possui uma prioridade,
sendo possivel remover o update com maior prioridade.
Os updates devem ser comutativos, ou seja, o estado
da estrutura deve ser o mesmo independente da ordem
que eles sejam aplicados.
Complexidades:
update - O(log(n) + T(n))
query - T(n)
pop - O(log(n) * T(n)) amortizado
onde T(n) eh a complexidade do update
assumes all priorities are distinct
Link original: priorityQueueDs.cpp
Código
template<typename DS, typename UPD> struct priority_queue_ds {
DS D;
vector<tuple<UPD, int, int>> upd; // {u, p, idx_in_pos}
set<pair<int, int>> st;
vector<int> pos;
priority_queue_ds(int n) : D(n) {}
void update(UPD u, int p) {
D.update(u);
st.emplace(p, pos.size());
upd.emplace_back(u, p, pos.size());
pos.push_back(upd.size() - 1);
}
int query(int a) {
return D.find(a);
}
void pop() {
int k = 1, min_p; // k = number of pops we will do
vector<tuple<UPD, int, int>> small, big;
auto it = st.end();
for (int qt = 0; qt++ < (k+1)/2;) {
it--;
min_p = it->first;
int i = pos[it->second];
if (qt > 1) big.push_back(upd[i]);
k = max<int>(k, upd.size() - i);
}
for (int i = 0; i < k; i++) {
D.rollback();
auto [u, p, idx] = upd.rbegin()[i];
if (p < min_p) small.emplace_back(u, p, idx);
}
st.erase(prev(st.end()));
upd.erase(upd.end() - k, upd.end());
small.insert(small.end(), big.rbegin(), big.rend());
for (auto [u, p, idx] : small) {
D.update(u);
upd.emplace_back(u, p, idx);
pos[idx] = upd.size() - 1;
}
}
};