Sobre

vector da NASA

Um pouco mais rapido q a treap

O construtor a partir do vector

eh linear, todas as outras operacoes

custam O(log(n)) amortizado

Link original: splaytreeImplicita.cpp

Código

  template<typename T> struct splay {
	struct node {
		node *ch[2], *p;
		int sz;
		T val, sub, lazy;
		bool rev;
		node(T v) {
			ch[0] = ch[1] = p = NULL;
			sz = 1;
			sub = val = v;
			lazy = 0;
			rev = false;
		}
		void prop() {
			if (lazy) {
				val += lazy, sub += lazy*sz;
				if (ch[0]) ch[0]->lazy += lazy;
				if (ch[1]) ch[1]->lazy += lazy;
			}
			if (rev) {
				swap(ch[0], ch[1]);
				if (ch[0]) ch[0]->rev ^= 1;
				if (ch[1]) ch[1]->rev ^= 1;
			}
			lazy = 0, rev = 0;
		}
		void update() {
			sz = 1, sub = val;
			for (int i = 0; i < 2; i++) if (ch[i]) {
				ch[i]->prop();
				sz += ch[i]->sz;
				sub += ch[i]->sub;
			}
		}
	};

	node* root;

	splay() { root = NULL; }
	splay(node* x) {
		root = x;
		if (root) root->p = NULL;
	}
	splay(vector<T> v) { // O(n)
		root = NULL;
		for (T i : v) {
			node* x = new node(i);
			x->ch[0] = root;
			if (root) root->p = x;
			root = x;
			root->update();
		}
	}
	splay(const splay& t) {
		throw logic_error("Nao copiar a splay!");
	}
	~splay() {
		vector<node*> q = {root};
		while (q.size()) {
			node* x = q.back(); q.pop_back();
			if (!x) continue;
			q.push_back(x->ch[0]), q.push_back(x->ch[1]);
			delete x;
		}
	}

	int size(node* x) { return x ? x->sz : 0; }
	void rotate(node* x) { // x vai ficar em cima
		node *p = x->p, *pp = p->p;
		if (pp) pp->ch[pp->ch[1] == p] = x;
		bool d = p->ch[0] == x;
		p->ch[!d] = x->ch[d], x->ch[d] = p;
		if (p->ch[!d]) p->ch[!d]->p = p;
		x->p = pp, p->p = x;
		p->update(), x->update();
	}
	node* splaya(node* x) {
		if (!x) return x;
		root = x, x->update();
		while (x->p) {
			node *p = x->p, *pp = p->p;
			if (!pp) return rotate(x), x; // zig
			if ((pp->ch[0] == p)^(p->ch[0] == x))
				rotate(x), rotate(x); // zigzag
			else rotate(p), rotate(x); // zigzig
		}
		return x;
	}
	node* find(int v) {
		if (!root) return NULL;
		node *x = root;
		int key = 0;
		while (1) {
			x->prop();
			bool d = key + size(x->ch[0]) < v;
			if (key + size(x->ch[0]) != v and x->ch[d]) {
				if (d) key += size(x->ch[0])+1;
				x = x->ch[d];
			} else break;
		}
		return splaya(x);
	}
	int size() { return root ? root->sz : 0; }
	void join(splay<T>& l) { // assume que l < *this
		if (!size()) swap(root, l.root);
		if (!size() or !l.size()) return;
		node* x = l.root;
		while (1) {
			x->prop();
			if (!x->ch[1]) break;
			x = x->ch[1];
		}
		l.splaya(x), root->prop(), root->update();
		x->ch[1] = root, x->ch[1]->p = x;
		root = l.root, l.root = NULL;
		root->update();
	}
	node* split(int v) { // retorna os elementos < v
		if (v <= 0) return NULL;
		if (v >= size()) {
			node* ret = root;
			root = NULL;
			ret->update();
			return ret;
		}
		find(v);
		node* l = root->ch[0];
		root->ch[0] = NULL;
		if (l) l->p = NULL;
		root->update();
		return l;
	}
	T& operator [](int i) {
		find(i);
		return root->val;
	}
	void push_back(T v) { // O(1)
		node* r = new node(v);
		r->ch[0] = root;
		if (root) root->p = r;
		root = r, root->update();
	}
	T query(int l, int r) {
		splay<T> M(split(r+1));
		splay<T> L(M.split(l));
		T ans = M.root->sub;
		M.join(L), join(M);
		return ans;
	}
	void update(int l, int r, T s) {
		splay<T> M(split(r+1));
		splay<T> L(M.split(l));
		M.root->lazy += s;
		M.join(L), join(M);
	}
	void reverse(int l, int r) {
		splay<T> M(split(r+1));
		splay<T> L(M.split(l));
		M.root->rev ^= 1;
		M.join(L), join(M);
	}
	void erase(int l, int r) {
		splay<T> M(split(r+1));
		splay<T> L(M.split(l));
		join(L);
	}
};