On this page
article
Distinct Range Query com Update
Sobre
build - O(n log(n))
query - O(log^2(n))
update - O(log^2(n))
Link original: distinctUpdate.cpp
Código
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <class T>
using ord_set = tree<T, null_type, less<T>, rb_tree_tag,
tree_order_statistics_node_update>;
int v[MAX], n, nxt[MAX], prv[MAX];
map<int, set<int> > ocor;
namespace bit {
ord_set<pair<int, int>> bit[MAX];
void build() {
for (int i = 1; i <= n; i++) bit[i].insert({nxt[i-1], i-1});
for (int i = 1; i <= n; i++) {
int j = i + (i&-i);
if (j <= n) for (auto x : bit[i]) bit[j].insert(x);
}
}
int pref(int p, int x) {
int ret = 0;
for (; p; p -= p&-p) ret += bit[p].order_of_key({x, -INF});
return ret;
}
int query(int l, int r, int x) {
return pref(r+1, x) - pref(l, x);
}
void update(int p, int x) {
int p2 = p;
for (p++; p <= n; p += p&-p) {
bit[p].erase({nxt[p2], p2});
bit[p].insert({x, p2});
}
}
}
void build() {
for (int i = 0; i < n; i++) nxt[i] = INF;
for (int i = 0; i < n; i++) prv[i] = -INF;
vector<pair<int, int>> t;
for (int i = 0; i < n; i++) t.push_back({v[i], i});
sort(t.begin(), t.end());
for (int i = 0; i < n; i++) {
if (i and t[i].first == t[i-1].first)
prv[t[i].second] = t[i-1].second;
if (i+1 < n and t[i].first == t[i+1].first)
nxt[t[i].second] = t[i+1].second;
}
for (int i = 0; i < n; i++) ocor[v[i]].insert(i);
bit::build();
}
void muda(int p, int x) {
bit::update(p, x);
nxt[p] = x;
}
int query(int a, int b) {
return b-a+1 - bit::query(a, b, b+1);
}
void update(int p, int x) { // mudar valor na pos. p para x
if (prv[p] > -INF) muda(prv[p], nxt[p]);
if (nxt[p] < INF) prv[nxt[p]] = prv[p];
ocor[v[p]].erase(p);
if (!ocor[x].size()) {
muda(p, INF);
prv[p] = -INF;
} else if (*ocor[x].rbegin() < p) {
int i = *ocor[x].rbegin();
prv[p] = i;
muda(p, INF);
muda(i, p);
} else {
int i = *ocor[x].lower_bound(p);
if (prv[i] > -INF) {
muda(prv[i], p);
prv[p] = prv[i];
} else prv[p] = -INF;
prv[i] = p;
muda(p, i);
}
v[p] = x; ocor[x].insert(p);
}