On this page
article
SegTree Colorida
Sobre
Cada posicao tem um valor e uma cor
O construtor receve um vector de {valor, cor}
e o numero de cores (as cores devem estar em [0, c-1])
query(c, a, b) retorna a soma dos valores
de todo mundo em [a, b] que tem cor c
update(c, a, b, x) soma x em todo mundo em
[a, b] que tem cor c
paint(c1, c2, a, b) faz com que todo mundo
em [a, b] que tem cor c1 passe a ter cor c2
Complexidades:
construir - O(n log(n)) espaco e tempo
query - O(log(n))
update - O(log(n))
paint - O(log(n)) amortizado
Link original: segTreeColor.cpp
Código
struct seg_color {
struct node {
node *l, *r;
int cnt;
ll val, lazy;
node() : l(NULL), r(NULL), cnt(0), val(0), lazy(0) {}
void update() {
cnt = 0, val = 0;
for (auto i : {l, r}) if (i) {
i->prop();
cnt += i->cnt, val += i->val;
}
}
void prop() {
if (!lazy) return;
val += lazy*(ll)cnt;
for (auto i : {l, r}) if (i) i->lazy += lazy;
lazy = 0;
}
};
int n;
vector<node*> seg;
seg_color(vector<pair<int, int>>& v, int c) : n(v.size()), seg(c, NULL) {
for (int i = 0; i < n; i++)
seg[v[i].second] = insert(seg[v[i].second], i, v[i].first, 0, n-1);
}
~seg_color() {
queue<node*> q;
for (auto i : seg) q.push(i);
while (q.size()) {
auto i = q.front(); q.pop();
if (!i) continue;
q.push(i->l), q.push(i->r);
delete i;
}
}
node* insert(node* at, int idx, int val, int l, int r) {
if (!at) at = new node();
if (l == r) return at->cnt = 1, at->val = val, at;
int m = (l+r)/2;
if (idx <= m) at->l = insert(at->l, idx, val, l, m);
else at->r = insert(at->r, idx, val, m+1, r);
return at->update(), at;
}
ll query(node* at, int a, int b, int l, int r) {
if (!at or b < l or r < a) return 0;
at->prop();
if (a <= l and r <= b) return at->val;
int m = (l+r)/2;
return query(at->l, a, b, l, m) + query(at->r, a, b, m+1, r);
}
ll query(int c, int a, int b) { return query(seg[c], a, b, 0, n-1); }
void update(node* at, int a, int b, int x, int l, int r) {
if (!at or b < l or r < a) return;
at->prop();
if (a <= l and r <= b) {
at->lazy += x;
return void(at->prop());
}
int m = (l+r)/2;
update(at->l, a, b, x, l, m), update(at->r, a, b, x, m+1, r);
at->update();
}
void update(int c, int a, int b, int x) { update(seg[c], a, b, x, 0, n-1); }
void paint(node*& from, node*& to, int a, int b, int l, int r) {
if (to == from or !from or b < l or r < a) return;
from->prop();
if (to) to->prop();
if (a <= l and r <= b) {
if (!to) {
to = from;
from = NULL;
return;
}
int m = (l+r)/2;
paint(from->l, to->l, a, b, l, m), paint(from->r, to->r, a, b, m+1, r);
to->update();
delete from;
from = NULL;
return;
}
if (!to) to = new node();
int m = (l+r)/2;
paint(from->l, to->l, a, b, l, m), paint(from->r, to->r, a, b, m+1, r);
from->update(), to->update();
}
void paint(int c1, int c2, int a, int b) { paint(seg[c1], seg[c2], a, b, 0, n-1); }
};