On this page
article
SegTreap
Sobre
Muda uma posicao do plano, e faz query de operacao
associativa e comutativa em retangulo
Mudar ZERO e op
Esparso nas duas coordenadas, inicialmente eh tudo ZERO
Para query com distancia de manhattan <= d, faca
nx = x+y, ny = x-y
Update em (nx, ny), query em ((nx-d, ny-d), (nx+d, ny+d))
Valores no X tem que ser de 0 ateh NX
Para q operacoes, usa O(q log(NX)) de memoria, e as
operacoes custa O(log(q) log(NX))
Link original: segTreap.cpp
Código
const int ZERO = INF;
const int op(int l, int r) { return min(l, r); }
mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count());
template<typename T> struct treap {
struct node {
node *l, *r;
int p;
pair<ll, ll> idx; // {y, x}
T val, mi;
node(ll x, ll y, T val_) : l(NULL), r(NULL), p(rng()),
idx(pair(y, x)), val(val_), mi(val) {}
void update() {
mi = val;
if (l) mi = op(mi, l->mi);
if (r) mi = op(mi, r->mi);
}
};
node* root;
treap() { root = NULL; }
~treap() {
vector<node*> q = {root};
while (q.size()) {
node* x = q.back(); q.pop_back();
if (!x) continue;
q.push_back(x->l), q.push_back(x->r);
delete x;
}
}
treap(treap&& t) : treap() { swap(root, t.root); }
void join(node* l, node* r, node*& i) { // assume que l < r
if (!l or !r) return void(i = l ? l : r);
if (l->p > r->p) join(l->r, r, l->r), i = l;
else join(l, r->l, r->l), i = r;
i->update();
}
void split(node* i, node*& l, node*& r, pair<ll, ll> idx) {
if (!i) return void(r = l = NULL);
if (i->idx < idx) split(i->r, i->r, r, idx), l = i;
else split(i->l, l, i->l, idx), r = i;
i->update();
}
void update(ll x, ll y, T v) {
node *L, *M, *R;
split(root, M, R, pair(y, x+1)), split(M, L, M, pair(y, x));
if (M) M->val = M->mi = v;
else M = new node(x, y, v);
join(L, M, M), join(M, R, root);
}
T query(ll ly, ll ry) {
node *L, *M, *R;
split(root, M, R, pair(ry, LINF)), split(M, L, M, pair(ly, 0));
T ret = M ? M->mi : ZERO;
join(L, M, M), join(M, R, root);
return ret;
}
};
template<typename T> struct segtreap {
vector<treap<T>> seg;
vector<int> ch[2];
ll NX;
segtreap(ll NX_) : seg(1), NX(NX_) { ch[0].push_back(-1), ch[1].push_back(-1); }
int get_ch(int i, int d){
if (ch[d][i] == -1) {
ch[d][i] = seg.size();
seg.emplace_back();
ch[0].push_back(-1), ch[1].push_back(-1);
}
return ch[d][i];
}
T query(ll lx, ll rx, ll ly, ll ry, int p, ll l, ll r) {
if (rx < l or r < lx) return ZERO;
if (lx <= l and r <= rx) return seg[p].query(ly, ry);
ll m = l + (r-l)/2;
return op(query(lx, rx, ly, ry, get_ch(p, 0), l, m),
query(lx, rx, ly, ry, get_ch(p, 1), m+1, r));
}
T query(ll lx, ll rx, ll ly, ll ry) { return query(lx, rx, ly, ry, 0, 0, NX); }
void update(ll x, ll y, T val, int p, ll l, ll r) {
if (l == r) return seg[p].update(x, y, val);
ll m = l + (r-l)/2;
if (x <= m) update(x, y, val, get_ch(p, 0), l, m);
else update(x, y, val, get_ch(p, 1), m+1, r);
seg[p].update(x, y, val);
}
void update(ll x, ll y, T val) { update(x, y, val, 0, 0, NX); }
};