洛谷 P3380 模板 二逼平衡树 线段树套平衡树

洛谷 P3380 模板 二逼平衡树 线段树套平衡树

title

Code

#include <cstdio>
#include <cstdlib>

using namespace std;

const int N = 1800010, INF = 1000000000;

struct Treap {

	int l[N], r[N], d[N], siz[N], cnt[N], val[N];
	int tot, rt, ERR;



	int mk(int v) {
		val[++tot] = v;
		d[tot] = rand();
		siz[tot] = 1;
		cnt[tot] = 1;
		return tot;
	}

	int update(int x) {
		return siz[x] = siz[l[x]] + siz[r[x]] + cnt[x];
	}

	int leftRotate(int &x) {
		int tmp = r[x];
		r[x] = l[tmp];
		l[tmp] = x;
		x = tmp;
		update(l[x]);
		update(x);
		return x;
	}

	int rightRotate(int &x) {
		int tmp = l[x];
		l[x] = r[tmp];
		r[tmp] = x;
		x = tmp;
		update(r[x]);
		update(x);
		return x;
	}

	void insert(int &x, int v) {
		if (!x) {
			x = mk(v);
			return ;
		}
		if (v == val[x]) ++cnt[x];
		else {
			if (v < val[x]) {
				insert(l[x], v);
				if (d[x] < d[l[x]])
					rightRotate(x);
			} else {
				insert(r[x], v);
				if (d[x] < d[r[x]])
					leftRotate(x);
			}
		}
		update(x);
		return ;
	}

	void erase(int &x, int v) {
		if (!x) return ;
		if (v == val[x]) {
			if (cnt[x] > 1) --cnt[x], update(x);
			else if (!l[x] && !r[x]) x = 0;
			else {
				if (!r[x] || d[r[x]] < d[l[x]]) rightRotate(x), erase(r[x], v);
				else leftRotate(x), erase(l[x], v);
				update(x);
			}
			return ;
		}
		if (v < val[x]) erase(l[x], v);
		else erase(r[x], v);
		update(x);
		return ;
	}

	void del(int &x, int v) {
		if (!x) return ;
		if (v == val[x]) {
			cnt[x] = 1, update(x);
			if (!l[x] && !r[x]) x = 0;
			else {
				if (!r[x] || d[r[x]] < d[l[x]]) rightRotate(x), del(r[x], v);
				else leftRotate(x), del(l[x], v);
				update(x);
			}
			return ;
		}
		if (v < val[x]) del(l[x], v);
		else del(r[x], v);
		update(x);
		return ;
	}

	int rank(int rt, int v) {
		int x, ans = 0;
		for (x = rt; x;) {
			if (v < val[x]) x = l[x];
			else if (v > val[x]) ans += siz[l[x]] + cnt[x], x = r[x];
			else return ans + siz[l[x]] + 1;
		}
		return ans + 1;
	}

	int value(int rt, int v) {
		int x;
		for (x = rt; x;) {
			if (v <= siz[l[x]]) x = l[x];
			else if (v <= siz[l[x]] + cnt[x]) return val[x];
			else v -= siz[l[x]] + cnt[x], x = r[x];
		}
		return ERR;
	}

	bool find(int rt, int v) {
		int x;
		for (x = rt; x;) {
			if (v < val[x]) x = l[x];
			else if (v > val[x]) x = r[x];
			else return 1;
		}
		return 0;
	}

	int count(int rt, int v) {
		int x;
		for (x = rt; x;) {
			if (v < val[x]) x = l[x];
			else if (v > val[x]) x = r[x];
			else return cnt[x];
		}
		return ERR;
	}

	int pre(int rt, int v) {
		int res = ERR;
		for (int x = rt; x;)
			if (val[x] < v) res = val[x], x = r[x];
			else x = l[x];
		return res;
	}

	int nxt(int rt, int v) {
		int res = ERR;
		for (int x = rt; x;)
			if (val[x] > v) res = val[x], x = l[x];
			else x = r[x];
		return res;
	}

	int max(int rt) {
		int x;
		for (x = rt; r[x]; x = r[x]);
		return val[x];
	}

	int min(int rt) {
		int x;
		for (x = rt; l[x]; x = l[x]);
		return val[x];
	}

	int clear(int error) {
		rt = tot = 0;
		return ERR = error;
	}

	int error() {
		return ERR;
	}

	void insert(int x) {
		insert(rt, x);
		return ;
	}

	void erase(int x) {
		erase(rt, x);
		return ;
	}

	void del(int x) {
		del(rt, x);
		return ;
	}

	int rank(int v) {
		return rank(rt, v);
	}

	int value(int v) {
		return value(rt, v);
	}

	bool find(int v) {
		return find(rt, v);
	}

	int count(int v) {
		return count(rt, v);
	}

	int pre(int v) {
		return pre(rt, v);
	}

	int nxt(int v) {
		return nxt(rt, v);
	}

	int max() {
		return max(rt);
	}

	int min() {
		int x;
		for (x = rt; l[x]; x = l[x]);
		return min(rt);
	}

	int size(int rt) {
		return siz[rt];
	}

	bool empty(int rt) {
		return !siz[rt];
	}

	int size() {
		return siz[rt];
	}

	bool empty() {
		return !siz[rt];
	}



	/*
	int clear(int error)
		init the treap, the error result is error
		return the error

	int error()
		return the error

	int size()
		return how many numbers in treap

	bool empty()
		return true or false
		true : the treap is empty
		false : the treap isn't empty

	void insert(int x)
		insert x to the treap

	void erase(int x)
		delete x in the treap

	void del(int x)
		delete all x in the treap
		
	int rank(int v)
		return v 's rank

	int value(int v)
		return the vth small number

	bool find(int v)
		return true or false
		true : v is in the treap
		false : v isn't in the treap

	int count(int v)
		return how many v in the treap

	int pre(int v)
		return x
		x < v
		x is the biggest

	int nxt(int v)
		return x
		x > v
		x is the smallest

	int max()
		return x
		x is the biggest

	int min()
		return x
		x is the smallest
	*/
} ;



struct Segment {
	int rt[N], n, err, mn, mx;
	int* s;
	Treap t;

	int min(int x, int y) {
		return x < y ? x : y;
	}

	int max(int x, int y) {
		return x > y ? x : y;
	}

	void build(int k, int l, int r) {
		rt[k] = 0;
		for (int i = l; i <= r; ++i)
			t.insert(rt[k], s[i]);
		if (l < r) {
			int mid = (l + r) >> 1;
			build(k << 1, l, mid);
			build(k << 1 | 1, mid + 1, r);
		}
		return ;
	}

	int rank(int k, int l, int r, int x, int y, int v) {
		if (x <= l && r <= y)
			return t.rank(rt[k], v) - 1;
		int mid = (l + r) >> 1, res = 0;
		if (x <= mid)
			res += rank(k << 1, l, mid, x, y, v);
		if (y > mid)
			res += rank(k << 1 | 1, mid + 1, r, x, y, v);
		return res;
	}

	int value(int l, int r, int v) {
		int el, er, mid;
		for (el = mn, er = mx; el < er;) {
			mid = (el + er + 1) >> 1;
			if (rank(1, 1, n, l, r, mid) < v)
				el = mid;
			else
				er = mid - 1;
		}
		return el;
	}

	void modify(int k, int l, int r, int x, int v) {
		t.erase(rt[k], s[x]);
		t.insert(rt[k], v);
		mn = min(mn, v);
		mx = max(mx, v);
		if (l == r)
			return;
		int mid = (l + r) >> 1;
		if (x <= mid)
			modify(k << 1, l, mid, x, v);
		if (x > mid)
			modify(k << 1 | 1, mid + 1, r, x, v);
		return ;
	}

	int pre(int k, int l, int r, int x, int y, int v) {
		if (x <= l && r <= y)
			return t.pre(rt[k], v);
			
		int mid = (l + r) >> 1, ans = mn - 1;
		if (x <= mid) {
			int res = pre(k << 1, l, mid, x, y, v);
			if (res != err)
				ans = max(ans, res);
		}
		if (y > mid) {
			int res = pre(k << 1 | 1, mid + 1, r, x, y, v);
			if (res != err)
				ans = max(ans, res);
		}
		if (ans == mn - 1)
			return err;
		return ans;
	}

	int nxt(int k, int l, int r, int x, int y, int v) {
		if (x <= l && r <= y)
			return t.nxt(rt[k], v);
			
		int mid = (l + r) >> 1, ans = mx + 1;
		if (x <= mid) {
			int res = nxt(k << 1, l, mid, x, y, v);
			if (res != err)
				ans = min(ans, res);
		}
		if (y > mid) {
			int res = nxt(k << 1 | 1, mid + 1, r, x, y, v);
			if (res != err)
				ans = min(ans, res);
		}
		if (ans == mx + 1)
			return err;
		return ans;
	}

	void build(int n, int inf, int error, int* s) {
		mn = inf;
		mx = -inf;
		this->n = n;
		this->s = s;
		this->err = error;
		for (int i = 1; i <= n; ++i) {
			mn = min(mn, s[i]);
			mx = max(mx, s[i]);
		}
		t.clear(error);
		build(1, 1, n);
		return ;
	}

	int rank(int l, int r, int v) {
		return rank(1, 1, n, l, r, v) + 1;
	}

	void modify(int x, int v) {
		modify(1, 1, n, x, v);
		s[x] = v;
		return ;
	}

	int pre(int x, int y, int v) {
		return pre(1, 1, n, x, y, v);
	}

	int nxt(int x, int y, int v) {
		return nxt(1, 1, n, x, y, v);
	}
} ;

Segment tr;

int s[N];

int main() {
	int n, q, opt, l, r, v;
	scanf("%d %d", &n, &q);
	for (int i = 1; i <= n; ++i)
		scanf("%d", &s[i]);
	tr.build(n, INF, -1, s);
	for (; q; --q) {
		scanf("%d %d %d", &opt, &l, &r);
		if (opt == 3) 
			tr.modify(l, r);
		else {
			scanf("%d", &v);
			if (opt == 1) printf("%d\n", tr.rank(l, r, v));
			else if (opt == 2) printf("%d\n", tr.value(l, r, v));
			else if (opt == 4)  {
				int res = tr.pre(l, r, v);
				printf("%d\n", res == -1 ? -2147483647 : res);
			} else {
				int res = tr.nxt(l, r, v);
				printf("%d\n", res == -1 ? 2147483647 : res);
			}
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值