【BZOJ3217】ALOEXT

【题目链接】

【思路要点】

  • 替罪羊树套权值线段树。
  • 时间复杂度\(O(NLog^2N)\)。
  • 由于常数较大,笔者的代码无法在BZOJ上通过。

【代码】

/*TLE of Large Constant*/
#include<bits/stdc++.h>
using namespace std;
#define MAXN	400005
#define MAXV	1048576
#define MAXLOG	20
#define MAXP	30000005
#define ALPHA	0.78
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
void getopt(char &c) {
	c = getchar();
	while (c != 'I' && c != 'D' && c != 'C' && c != 'F')
		c = getchar();
}
struct Segment_Tree {
	int now, root[MAXN];
	int top, mem[MAXP];
	int lc[MAXP], rc[MAXP], sum[MAXP];
	void init(int n) {
		for (int i = 1; i <= n; i++)
			mem[i] = n - i + 1;
		top = n;
	}
	int new_node() {
		int tmp = mem[top--];
		lc[tmp] = rc[tmp] = 0;
		sum[tmp] = 0;
		return tmp;
	}
	void recycle(int x) {
		mem[++top] = x;
	}
	void dfs(int x) {
		if (lc[x]) dfs(lc[x]);
		if (rc[x]) dfs(rc[x]);
		recycle(x);
	}
	void clear(int x) {
		if (root[x]) dfs(root[x]);
		root[x] = 0;
	}
	void modify(int &root, int depth, int value, int delta) {
		if (root == 0) root = new_node();
		sum[root] += delta;
		if (depth == 0) return;
		int bit = 1 << (depth - 1);
		if (bit & value) modify(rc[root], depth - 1, value ^ bit, delta);
		else modify(lc[root], depth - 1, value, delta);
	}
	void modify(int x, int v, int d) {
		modify(root[x], MAXLOG, v, d);
	}
	int query(int value, int len, int *home) {
		for (int i = 1; i <= len; i++)
			home[i] = root[home[i]];
		for (int depth = MAXLOG, bit = 1 << (MAXLOG - 1); depth > 0; depth--, bit >>= 1) {
			if (value & bit) {
				int tsum = 0;
				for (int i = 1; i <= len; i++)
					tsum += sum[lc[home[i]]];
				if (tsum >= 1) {
					for (int i = 1; i <= len; i++)
						home[i] = lc[home[i]];
				} else {
					value ^= bit;
					for (int i = 1; i <= len; i++)
						home[i] = rc[home[i]];
				}
			} else {
				int tsum = 0;
				for (int i = 1; i <= len; i++)
					tsum += sum[rc[home[i]]];
				if (tsum >= 1) {
					value ^= bit;
					for (int i = 1; i <= len; i++)
						home[i] = rc[home[i]];
				} else {
					for (int i = 1; i <= len; i++)
						home[i] = lc[home[i]];
				}
			}
		}
		return value;
	}
} SMT;
struct Scapegoat_Tree {
	int root, reroot;
	int len, tindex[MAXN];
	int tMax, tNax, home[MAXN];
	int top, mem[MAXN];
	int lc[MAXN], rc[MAXN];
	int index[MAXN], size[MAXN], rsize[MAXN];
	int Max[MAXN], Nax[MAXN];
	void init(int n) {
		for (int i = 1; i <= n; i++)
			mem[i] = n - i + 1;
		top = n;
		Max[0] = Nax[0] = index[0] = -1;
	}
	int new_node() {
		int tmp = mem[top--];
		lc[tmp] = rc[tmp] = 0;
		index[tmp] = -1;
		size[tmp] = 0;
		rsize[tmp] = 0;
		SMT.clear(tmp);
		return tmp;
	}
	void recycle(int x) {
		SMT.clear(x);
		mem[++top] = x;
	}
	void update(int x) {
		if (index[x] != -1) size[x] = 1;
		else size[x] = 0;
		size[x] += size[lc[x]];
		size[x] += size[rc[x]];
		rsize[x] = 1;
		rsize[x] += rsize[lc[x]];
		rsize[x] += rsize[rc[x]];
		Max[x] = index[x];
		Nax[x] = -1;
		int tmp;
		tmp = Max[lc[x]];
		if (tmp > Max[x]) Nax[x] = Max[x], Max[x] = tmp;
		else Nax[x] = max(Nax[x], tmp);
		tmp = Max[rc[x]];
		if (tmp > Max[x]) Nax[x] = Max[x], Max[x] = tmp;
		else Nax[x] = max(Nax[x], tmp);
		tmp = Nax[lc[x]];
		if (tmp > Max[x]) Nax[x] = Max[x], Max[x] = tmp;
		else Nax[x] = max(Nax[x], tmp);
		tmp = Nax[rc[x]];
		if (tmp > Max[x]) Nax[x] = Max[x], Max[x] = tmp;
		else Nax[x] = max(Nax[x], tmp);
	}
	void dfs(int root) {
		if (root != reroot) recycle(root);
		if (lc[root]) dfs(lc[root]);
		if (index[root] != -1) tindex[++len] = index[root];
		if (rc[root]) dfs(rc[root]);
	}
	void rebuild(int root, int l, int r) {
		for (int i = l; i <= r; i++)
			SMT.modify(root, tindex[i], 1);
		if (l == r) {
			index[root] = tindex[l];
			update(root);
			return;
		}
		int mid = (l + r) / 2;
		index[root] = -1;
		lc[root] = new_node();
		rebuild(lc[root], l, mid);
		rc[root] = new_node();
		rebuild(rc[root], mid + 1, r);
		update(root);
	}
	void rebuild(int root) {
		len = 0;
		dfs(root);
		lc[root] = rc[root] = 0;
		index[root] = size[root] = 0;
		SMT.clear(root);
		rebuild(root, 1, len);
	}
	void index_init(int n, int *a) {
		for (int i = 1; i <= n; i++)
			tindex[i] = a[i];
		root = new_node();
		rebuild(root, 1, n);
	}
	bool unbalance(int root) {
		return max(rsize[lc[root]], rsize[rc[root]]) > rsize[root] * ALPHA + 1;
	}
	int cnt(int root) {return index[root] != -1; }
	void insert(int &root, int pos, int value) {
		if (cnt(root)) {
			int tmp = root, tnp = new_node();
			index[tnp] = Max[tnp] = value;
			Nax[tnp] = -1;
			size[tnp] = rsize[tnp] = 1;
			SMT.modify(tnp, value, 1);
			root = new_node();
			if (pos == 0) swap(tmp, tnp);
			lc[root] = tmp, rc[root] = tnp;
			SMT.modify(root, index[tmp], 1);
			SMT.modify(root, index[tnp], 1);
			update(root);
			return;
		}
		if (root == 0) {
			root = new_node();
			index[root] = Max[root] = value;
			Nax[root] = -1;
			size[root] = rsize[root] = 1;
			SMT.modify(root, value, 1);
			return;
		}
		SMT.modify(root, value, 1);
		if (pos <= size[lc[root]]) insert(lc[root], pos, value);
		else insert(rc[root], pos - size[lc[root]], value);
		update(root);
		if (unbalance(root)) reroot = root;
	}
	void insert(int pos, int value) {
		reroot = 0;
		insert(root, pos, value);
		if (reroot) rebuild(reroot);
	}
	int modify(int root, int pos, int value) { /*Return Value: Old Index*/
		SMT.modify(root, value, 1);
		if (cnt(root)) {
			int tmp = index[root];
			index[root] = value;
			update(root);
			SMT.modify(root, tmp, -1);
			return tmp;
		}
		if (pos <= size[lc[root]]) {
			int tmp = modify(lc[root], pos, value);
			SMT.modify(root, tmp, -1);
			update(root);
			return tmp;
		} else {
			pos -= size[lc[root]];
			int tmp = modify(rc[root], pos, value);
			SMT.modify(root, tmp, -1);
			update(root);
			return tmp;
		}
	}
	void modify(int pos, int value) {
		modify(root, pos, value);
	}
	int del(int &root, int pos) { /*Return Value: Old Index*/
		if (cnt(root)) {
			int tmp = index[root];
			recycle(root);
			root = 0;
			return tmp;
		}
		if (pos <= size[lc[root]]) {
			int tmp = del(lc[root], pos);
			SMT.modify(root, tmp, -1);
			update(root);
			return tmp;
		} else {
			pos -= size[lc[root]];
			int tmp = del(rc[root], pos);
			SMT.modify(root, tmp, -1);
			update(root);
			return tmp;
		}
	}
	void del(int pos) {
		del(root, pos);
	}
	void getquery(int root, int l, int r) {
		if (l == 1 && r == size[root]) {
			home[++len] = root;
			int tmp;
			tmp = Max[root];
			if (tmp > tMax) tNax = tMax, tMax = tmp;
			else tNax = max(tNax, tmp);
			tmp = Nax[root];
			if (tmp > tMax) tNax = tMax, tMax = tmp;
			else tNax = max(tNax, tmp);
			return;
		}
		int mid = size[lc[root]];
		if (mid >= l) getquery(lc[root], l, min(r, mid));
		if (mid + 1 <= r) getquery(rc[root], max(mid + 1, l) - mid, r - mid);
	}
	int query(int l, int r) {
		len = 0; tMax = tNax = -1;
		getquery(root, l, r);
		return SMT.query(tNax, len, home);
	}
} SGT;
int num[MAXN];
int main() {
	SMT.init(MAXP - 1);
	SGT.init(MAXN - 1);
	int lastans = 0;
	int n; read(n);
	int m; read(m);
	for (int i = 1; i <= n; i++)
		read(num[i]);
	SGT.index_init(n, num);
	for (int i = 1; i <= m; i++) {
		char opt; int l, r;
		getopt(opt);
		if (opt == 'I') {
			read(l), read(r);
			l = (l + lastans) % n;
			r = (r + lastans) % MAXV;
			SGT.insert(l, r); n++;
		}
		if (opt == 'D') {
			read(l);
			l = (l + lastans) % n;
			SGT.del(l + 1); n--;
		}
		if (opt == 'C') {
			read(l), read(r);
			l = (l + lastans) % n;
			r = (r + lastans) % MAXV;
			SGT.modify(l + 1, r);
		}
		if (opt == 'F') {
			read(l), read(r);
			l = (l + lastans) % n;
			r = (r + lastans) % n;
			printf("%d\n", lastans = SGT.query(l + 1, r + 1));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/80063069
今日推荐