【BZOJ1500】[NOI2005]维修数列【Splay】

http://www.lydsy.com/JudgeOnline/problem.php?id=1500

这神题终于过了...


主要是:

find()那里少写了一个pushdown()。

辣鸡回收写跪了。


似乎不用pushdown(root)...


/* Footprints In The Blood Soaked Snow */
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 500005, inf = 0x3f3f3f3f;

int n, m, num[maxn];

int son[maxn][2], pre[maxn], size[maxn], lx[maxn], rx[maxn], sum[maxn], mx[maxn], val[maxn];
int root, tot1, tot2, sta[maxn];
bool rev[maxn], same[maxn];

inline void newnode(int &x, int c, int f) {
	x = tot2 ? sta[tot2--] : ++tot1;
	son[x][0] = son[x][1] = 0;
	pre[x] = f;
	size[x] = 1;
	sum[x] = mx[x] = lx[x] = rx[x] = val[x] = c;
	rev[x] = same[x] = 0;
}

inline void pushup(int x) {
	int l = son[x][0], r = son[x][1];
	size[x] = size[l] + size[r] + 1;
	sum[x] = sum[l] + val[x] + sum[r];
	mx[x] = max(max(mx[l], mx[r]), max(0, rx[l]) + val[x] + max(0, lx[r]));
	lx[x] = max(lx[l], sum[l] + val[x] + max(0, lx[r]));
	rx[x] = max(rx[r], max(0, rx[l]) + val[x] + sum[r]);
}

inline void pushdown(int x) {
	int l = son[x][0], r = son[x][1];
	if(rev[x]) {
		rev[l] ^= 1; rev[r] ^= 1;
		swap(son[l][0], son[l][1]); swap(son[r][0], son[r][1]);
		swap(lx[l], rx[l]); swap(lx[r], rx[r]);
		rev[x] = 0;
	}
	if(same[x]) {
		if(l) same[l] = 1, val[l] = val[x], sum[l] = val[l] * size[l], lx[l] = rx[l] = mx[l] = max(val[l], sum[l]);
		if(r) same[r] = 1, val[r] = val[x], sum[r] = val[r] * size[r], lx[r] = rx[r] = mx[r] = max(val[r], sum[r]);
		same[x] = 0;
	}
}

inline void build(int &x, int l, int r, int f) {
	if(l > r) return;
	int mid = l + r >> 1;
	newnode(x, num[mid], f);
	build(son[x][0], l, mid - 1, x); build(son[x][1], mid + 1, r, x);
	pushup(x);
}

inline void init() {
	tot1 = tot2 = root = 0;
	son[0][0] = son[0][1] = pre[0] = size[0] = rev[0] = same[0] = sum[0] = val[0] = 0;
	lx[0] = rx[0] = mx[0] = -inf;
	newnode(root, -inf, 0);
	newnode(son[root][1], -inf, root);
	build(son[son[root][1]][0], 1, n, son[root][1]);
	pushup(son[root][1]); pushup(root);
}

inline void rotate(int x) {
	int y = pre[x], z = pre[y], type = son[y][1] == x;
	pre[son[y][type] = son[x][!type]] = y;
	pre[x] = z;
	if(z) son[z][son[z][1] == y] = x;
	pre[son[x][!type] = y] = x;
	pushup(y); pushup(x);
}

inline void splay(int x, int goal) {
	while(pre[x] != goal) {
		int y = pre[x], z = pre[y];
		if(z == goal) rotate(x);
		else if(son[z][0] == y ^ son[y][0] == x) rotate(x), rotate(x);
		else rotate(y), rotate(x);
	}
	if(goal == 0) root = x;
}

inline int find(int k) {
	int x = root;
	for(pushdown(x); k != size[son[x][0]] + 1; pushdown(x))
		if(k <= size[son[x][0]]) x = son[x][0];
		else k -= size[son[x][0]] + 1, x = son[x][1];
	return x;
}

inline void insert(int pos, int tot) {
	int x = find(pos + 1), y = find(pos + 2);
	splay(x, 0); splay(y, root);
	build(son[y][0], 1, tot, y);
	pushup(y); pushup(x);
}

inline void erase(int x) {
	if(!x) return;
	sta[++tot2] = x;
	erase(son[x][0]); erase(son[x][1]);
	son[x][0] = son[x][1] = pre[x] = rev[x] = same[x] = size[x] = 0;
}

inline void del(int pos, int tot) {
	int x = find(pos), y = find(pos + tot + 1);
	splay(x, 0); splay(y, root);
	erase(son[y][0]);
	son[y][0] = 0;
	pushup(son[root][1]); pushup(root);
}

inline void makesame(int pos, int tot, int c) {
	int x = find(pos), y = find(pos + tot + 1);
	splay(x, 0); splay(y, root);
	int u = son[y][0];
	same[u] = 1;
	val[u] = c;
	sum[u] = val[u] * size[u];
	lx[u] = rx[u] = mx[u] = max(val[u], sum[u]);
	pushup(son[root][1]); pushup(root);
}

inline void reverse(int pos, int tot) {
	int x = find(pos), y = find(pos + tot + 1);
	splay(x, 0); splay(y, root);
	int u = son[y][0];
	if(same[u]) return;
	rev[u] ^= 1;
	swap(son[u][0], son[u][1]);
	swap(lx[u], rx[u]);
	pushup(son[root][1]); pushup(root);
}

inline int getsum(int pos, int tot) {
	int x = find(pos), y = find(pos + tot + 1);
	splay(x, 0); splay(y, root);
	return sum[son[y][0]];
}

char opt[25];

int main() {
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i++) scanf("%d", &num[i]);

	init();
	
	int cnt = 1;
	while(m--) {
		scanf("%s", opt);
		if(opt[0] == 'I') {
			int pos, tot; scanf("%d%d", &pos, &tot);
			for(int i = 1; i <= tot; i++) scanf("%d", &num[i]);
			insert(pos, tot);
		}
		else if(opt[0] == 'D') {
			int pos, tot; scanf("%d%d", &pos, &tot);
			del(pos, tot);
		}
		else if(opt[0] == 'M' && opt[2] == 'K') {
			int pos, tot, c; scanf("%d%d%d", &pos, &tot, &c);
			makesame(pos, tot, c);
		}
		else if(opt[0] == 'R') {
			int pos, tot; scanf("%d%d", &pos, &tot);
			reverse(pos, tot);
		}
		else if(opt[0] == 'G') {
			int pos, tot; scanf("%d%d", &pos, &tot);
			printf("%d\n", getsum(pos, tot));
		}
		else if(opt[0] == 'M' && opt[2] == 'X')
			printf("%d\n", mx[root]);
	}
	return 0;
}


再写一遍。

/* Footprints In The Blood Soaked Snow */
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 500005, inf = 0x3f3f3f3f;

int n, m, num[maxn];
int son[maxn][2], size[maxn], pre[maxn], lx[maxn], rx[maxn], mx[maxn], sum[maxn], val[maxn];
int root, tot1, tot2, sta[maxn];
bool rev[maxn], same[maxn];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

inline void newnode(int &x, int c, int f) {
	x = tot2 ? sta[tot2--] : ++tot1;
	son[x][0] = son[x][1] = 0;
	pre[x] = f;
	size[x] = 1;
	lx[x] = rx[x] = mx[x] = sum[x] = val[x] = c;
	rev[x] = same[x] = 0;
}

inline void pushup(int x) {
	int l = son[x][0], r = son[x][1];
	size[x] = size[l] + size[r] + 1;
	sum[x] = sum[l] + val[x] + sum[r];
	mx[x] = max(max(mx[l], mx[r]), max(0, rx[l]) + val[x] + max(0, lx[r]));
	lx[x] = max(lx[l], sum[l] + val[x] + max(0, lx[r]));
	rx[x] = max(rx[r], max(0, rx[l]) + val[x] + sum[r]);
}

inline void pushdown(int x) {
	int l = son[x][0], r = son[x][1];
	if(rev[x]) {
		rev[l] ^= 1; rev[r] ^= 1;
		swap(son[l][0], son[l][1]); swap(son[r][0], son[r][1]);
		swap(lx[l], rx[l]); swap(lx[r], rx[r]);
		rev[x] = 0;
	}
	if(same[x]) {
		if(l) same[l] = 1, val[l] = val[x], sum[l] = val[l] * size[l], lx[l] = rx[l] = mx[l] = max(val[l], sum[l]);
		if(r) same[r] = 1, val[r] = val[x], sum[r] = val[r] * size[r], lx[r] = rx[r] = mx[r] = max(val[r], sum[r]);
		same[x] = 0;
	}
}

inline void build(int &x, int l, int r, int f) {
	if(l > r) return;
	int mid = l + r >> 1;
	newnode(x, num[mid], f);
	build(son[x][0], l, mid - 1, x); build(son[x][1], mid + 1, r, x);
	pushup(x);
}

inline void init() {
	tot1 = tot2 = root = 0;
	son[0][0] = son[0][1] = size[0] = pre[0] = sum[0] = val[0] = 0;
	lx[0] = rx[0] = mx[0] = -inf;
	newnode(root, -inf, 0);
	newnode(son[root][1], -inf, root);
	build(son[son[root][1]][0], 1, n, son[root][1]);
	pushup(son[root][1]); pushup(root);
}

inline void rotate(int x) {
	int y = pre[x], z = pre[y], type = son[y][1] == x;
	pre[son[y][type] = son[x][!type]] = y;
	pre[x] = z;
	if(z) son[z][son[z][1] == y] = x;
	pre[son[x][!type] = y] = x;
	pushup(y); pushup(x);
}

inline void splay(int x, int goal) {
	while(pre[x] ^ goal) {
		int y = pre[x], z = pre[y];
		if(z == goal) rotate(x);
		else if(son[z][1] == y ^ son[y][1] == x) rotate(x), rotate(x);
		else rotate(y), rotate(x);
	}
	if(goal == 0) root = x;
}

inline int find(int k) {
	int x = root;
	for(; k != size[son[x][0]] + 1; pushdown(x))
		if(k <= size[son[x][0]]) x = son[x][0];
		else k -= size[son[x][0]] + 1, x = son[x][1];
	return x;
}

inline void insert(int pos, int tot) {
	int x = find(pos + 1), y = find(pos + 2);
	splay(x, 0); splay(y, root);
	build(son[y][0], 1, tot, y);
	pushup(y); pushup(x);
}

inline void erase(int x) {
	if(!x) return;
	sta[++tot2] = x;
	erase(son[x][0]); erase(son[x][1]);
	son[x][0] = son[x][1] = pre[x] = size[x] = rev[x] = same[x] = 0;
}

inline void del(int pos, int tot) {
	int x = find(pos), y = find(pos + tot + 1);
	splay(x, 0); splay(y, root);
	erase(son[y][0]);
	son[y][0] = 0;
	pushup(y); pushup(x);
}

inline void makesame(int pos, int tot, int c) {
	int x = find(pos), y = find(pos + tot + 1);
	splay(x, 0); splay(y, root);
	int u = son[y][0];
	same[u] = 1;
	val[u] = c;
	sum[u] = val[u] * size[u];
	lx[u] = rx[u] = mx[u] = max(val[u], sum[u]);
	pushup(y); pushup(x);
}

inline void reverse(int pos, int tot) {
	int x = find(pos), y = find(pos + tot + 1);
	splay(x, 0); splay(y, root);
	int u = son[y][0];
	if(same[u]) return;
	rev[u] ^= 1;
	swap(son[u][0], son[u][1]);
	swap(lx[u], rx[u]);
	pushup(y); pushup(x);
}

inline int getsum(int pos, int tot) {
	int x = find(pos), y = find(pos + tot + 1);
	splay(x, 0); splay(y, root);
	return sum[son[y][0]];
}

char str[25];

int main() {
	n = iread(); m = iread();
	for(int i = 1; i <= n; i++) num[i] = iread();

	init();

	while(m--) {
		scanf("%s", str);
		if(str[2] == 'S') {
			int pos = iread(), tot = iread();
			for(int i = 1; i <= tot; i++) num[i] = iread();
			insert(pos, tot);
		}
		else if(str[2] == 'L') {
			int pos = iread(), tot = iread();
			del(pos, tot);
		}
		else if(str[2] == 'K') {
			int pos = iread(), tot = iread(), c = iread();
			makesame(pos, tot, c);
		}
		else if(str[2] == 'V') {
			int pos = iread(), tot = iread();
			reverse(pos, tot);
		}
		else if(str[2] == 'T') {
			int pos = iread(), tot = iread();
			printf("%d\n", getsum(pos, tot));
		}
		else if(str[2] == 'X')
			printf("%d\n", mx[root]);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值