[NOI2005] 维修数列 (Splay)

刚学平衡树的时候写了一天,莫名其妙A了,然后瞎jb改又改错了,然后并不知道到底哪里错了,于是放弃。

然后过了几个月又重新学了平衡树专题,再拿起这道神仙题,自以为思路清晰,然而又调了一天。虽然大体思路没有问题 (本来就是大力数据结构。。。),但是细小的错误很多,令人烦躁。

这道题还是反映了我代码能力的不足,在构思的时候也粗枝大叶,很难在一开始就把所有细节思考完备。还需努力。

题意

维护数列。
在这里插入图片描述

每个操作都不难,基本都是平衡树基本操作。 难在把那么多操作强行堆砌在同一题。

注意

1

空间有点紧,需要回收节点。

2

第2和4操作需要打标记。

需要明确一个节点有懒标记的意义:当前节点已经修改过了,但是他的儿子还没有修改。当然你的懒标记也可以表示当前节点也没有被修改过(不建议,因为到后面会比较麻烦),但是一定要在任何时候都清晰地知道那些节点需要 p u s h _ d o w n push\_down push_down

比如下面这张图:

在这里插入图片描述
r o t a t e rotate rotate之前,假如懒标记意义是自己修改过了,那么必须保证P和Q不带有标记,而A、B、C可以带标记。但假如懒标记意义是自己还没被修改,那么就需要对A、B、C、P、Q全部进行 p u s h _ d o w n push\_down push_down然后才可以旋转。

3

不要修改0号点的权值。为了保证0号点不会“影响查找第k个点”或者“最大子段和的更新”,
0号点 s i z = 0 , m a x _ s u m = − i n f siz=0,max\_sum=-inf siz=0,max_sum=inf

假如你像我一样在splay里面加了左右两个边界点的话,把边界的权值设为 − i n f -inf inf

4

不要复制粘贴,不然有可能死得不明不白。

finally

留足耐心。。。做好调半天的准备。。。

代码

不仅长得不行,而且慢得不行。

正常版

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x = 0, fh = 0;
	char c = getchar();
	while (c < '0' || c > '9'){if (c == '-') fh = 1; c = getchar();}
	while (c >= '0' && c <= '9') x = (x<<1)+(x<<3)+c-'0', c = getchar();
	return fh ? -x : x;
}
const int inf = 1e9+7;
const int N = 5e5+10;
namespace SPLAY
{
	struct TrashBin{
		int bin[N], bcnt, cnt;
		inline void recyc(int x){
			bin[++bcnt] = x;
		}
		inline int new_node(){
			if (bcnt) return bin[bcnt--];
			return ++cnt;
		}
	}bin;
	struct Node{
		int fa, ch[2];
		int siz, val, sum;
		int flp, all;
		int le, ri, tot;
		Node(){}
		Node(int _fa, int _val){
			ch[0] = ch[1] = flp = all = 0; siz = 1;
			fa = _fa; sum = val = _val;
			tot = _val; le = ri = max(0, _val);
		}
	}nd[N];
	int root;
	#define ls nd[u].ch[0]
	#define rs nd[u].ch[1]
	inline void push_down(int u){
		if (nd[u].all){
			nd[u].all = nd[u].flp = 0;
			if (ls > 2){
				nd[ls].val = nd[u].val;
				nd[ls].sum = nd[ls].val*nd[ls].siz;
				if (nd[u].val > 0) nd[ls].le = nd[ls].ri = nd[ls].tot = nd[ls].sum;
				else nd[ls].le = nd[ls].ri = 0, nd[ls].tot = nd[ls].val;
				nd[ls].all = 1;
			}
			if (rs > 2){
				nd[rs].val = nd[u].val;
				nd[rs].sum = nd[rs].val*nd[rs].siz;
				if (nd[u].val > 0) nd[rs].le = nd[rs].ri = nd[rs].tot = nd[rs].sum;
				else nd[rs].le = nd[rs].ri = 0, nd[rs].tot = nd[rs].val;
				nd[rs].all = 1;
			}
		}
		if (nd[u].flp){
			nd[u].flp = 0;
			nd[ls].flp ^= 1; nd[rs].flp ^= 1;
			swap(nd[ls].ch[0], nd[ls].ch[1]);
			swap(nd[ls].le, nd[ls].ri);
			swap(nd[rs].ch[0], nd[rs].ch[1]);
			swap(nd[rs].le, nd[rs].ri);
		}
	}
	inline void push_up(int u){
		nd[u].siz = nd[ls].siz+nd[rs].siz+1;
		nd[u].sum = nd[ls].sum+nd[rs].sum+nd[u].val;
		nd[u].le = max(nd[ls].le, nd[ls].sum+nd[u].val+nd[rs].le);
		nd[u].ri = max(nd[rs].ri, nd[rs].sum+nd[u].val+nd[ls].ri);
		nd[u].tot = max(max(nd[ls].tot, nd[rs].tot), nd[u].val+nd[ls].ri+nd[rs].le);
	}
	void reset(int le_bd, int ri_bd){
		nd[0] = Node(0, 0); nd[0].siz = 0; nd[0].tot = -inf;
		nd[1] = Node(0, le_bd);
		nd[2] = Node(1, ri_bd); nd[1].ch[1] = 2;
		push_up(1);
		root = 1; bin.cnt = 2; bin.bcnt = 0;
	}
	inline int son(int u){
		return nd[nd[u].fa].ch[1] == u;
	}
	inline void rotate(int u){
		int v = nd[u].fa, w = nd[v].fa;
		int vs = son(u), ws = son(v);
		nd[w].ch[ws] = u;
		nd[v].fa = u;
		nd[v].ch[vs] = nd[u].ch[vs^1];
		nd[nd[u].ch[vs^1]].fa = v;
		nd[u].fa = w;
		nd[u].ch[vs^1] = v;
		push_up(v); push_up(u);
	}
	inline void splay(int u, int goal){
		while (nd[u].fa != goal){
			if (nd[nd[u].fa].fa != goal) rotate(son(u) == son(nd[u].fa) ? nd[u].fa : u);
			rotate(u);
		}
		if (goal == 0) root = u;
	}
	#undef ls
	#undef rs
}
using namespace SPLAY;
int n, m, a[N];

inline void find_rnk(int root, int x)
{
	int u = root;
	while (u){
		push_down(u);
		if (nd[nd[u].ch[0]].siz >= x){u = nd[u].ch[0]; continue;}
		x -= nd[nd[u].ch[0]].siz+1;
		if (x == 0) break;
		u = nd[u].ch[1];
	}
	splay(u, nd[root].fa);
}

inline void insert(int pos, int tot, int *a)
{
	find_rnk(root, pos+2);
	find_rnk(nd[root].ch[0], pos+1);
	int u, fa = nd[root].ch[0];
	for (int i = 1; i <= tot; ++ i){
		u = bin.new_node();
		nd[fa].ch[1] = u;
		nd[u] = Node(fa, a[i]);
		fa = u;
	}
	splay(u, 0);
}

void del_dfs(int u)
{
	if (!u) return;
	bin.recyc(u);
	del_dfs(nd[u].ch[0]);
	del_dfs(nd[u].ch[1]);
}

inline void delet(int pos, int tot)
{
	find_rnk(root, pos);
	find_rnk(nd[root].ch[1], tot+1);
	del_dfs(nd[nd[root].ch[1]].ch[0]);
	nd[nd[root].ch[1]].ch[0] = 0;
	splay(nd[root].ch[1], 0);
}

inline void reverse(int pos, int tot)
{
	find_rnk(root, pos);
	find_rnk(nd[root].ch[1], tot+1);
	int u = nd[nd[root].ch[1]].ch[0];
	nd[u].flp ^= 1;
	swap(nd[u].ch[0], nd[u].ch[1]);
	swap(nd[u].le, nd[u].ri);
	push_down(u);
	splay(u, 0);
}

inline void make_same(int pos, int tot, int c)
{
	find_rnk(root, pos);
	find_rnk(nd[root].ch[1], tot+1);
	int u = nd[nd[root].ch[1]].ch[0];
	nd[u].all = 1; nd[u].val = c; nd[u].sum = c*nd[u].siz;
	if (c > 0) nd[u].le = nd[u].ri = nd[u].tot = nd[u].sum;
	else nd[u].le = nd[u].ri = 0, nd[u].tot = c;
	push_down(u);
	splay(u, 0);
}

inline int get_sum(int pos, int tot)
{
	find_rnk(root, pos);
	find_rnk(nd[root].ch[1], tot+1);
	return nd[nd[nd[root].ch[1]].ch[0]].sum;
}

int main()
{
	reset(-inf, -inf);
	n = read(); m = read();
	for (int i = 1; i <= n; ++ i) a[i] = read();
	insert(0, n, a);
	for (; m--; ){
		char opt[10]; int pos, tot, x;
		scanf("%s", opt);
		if (opt[2] == 'X') printf("%d\n", nd[root].tot);
		else {
			pos = read(); tot = read();
			if (opt[0] == 'G') printf("%d\n", get_sum(pos, tot));
			else if (opt[0] == 'R') reverse(pos, tot);
			else if (opt[2] == 'K') x = read(), make_same(pos, tot, x);
			else if (opt[0] == 'D') delet(pos, tot);
			else if (opt[0] == 'I'){
				for (int i = 1; i <= tot; ++ i) a[i] = read();
				insert(pos, tot, a);
			}
		}
	}
	return 0;
}

有调试

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x = 0, fh = 0;
	char c = getchar();
	while (c < '0' || c > '9'){if (c == '-') fh = 1; c = getchar();}
	while (c >= '0' && c <= '9') x = (x<<1)+(x<<3)+c-'0', c = getchar();
	return fh ? -x : x;
}
const int inf = 1e9+7;
const int N = 5e5+10;
namespace SPLAY
{
	struct TrashBin{
		int bin[N], bcnt, cnt;
		inline void recyc(int x){
			bin[++bcnt] = x;
		}
		inline int new_node(){
			if (bcnt) return bin[bcnt--];
			return ++cnt;
		}
	}bin;
	struct Node{
		int fa, ch[2];
		int siz, val, sum;
		int flp, all;
		int le, ri, tot;
		Node(){}
		Node(int _fa, int _val){
			ch[0] = ch[1] = flp = all = 0; siz = 1;
			fa = _fa; sum = val = _val;
			tot = _val; le = ri = max(0, _val);
		}
	}nd[N];
	int root;
	#define ls nd[u].ch[0]
	#define rs nd[u].ch[1]
	inline void push_down(int u){ // lazy_tag means that the current node has already been updated but sons haven't
		if (nd[u].all){
			nd[u].all = nd[u].flp = 0;
			if (ls > 2){
				nd[ls].val = nd[u].val;
				nd[ls].sum = nd[ls].val*nd[ls].siz;
				if (nd[u].val > 0) nd[ls].le = nd[ls].ri = nd[ls].tot = nd[ls].sum;
				else nd[ls].le = nd[ls].ri = 0, nd[ls].tot = nd[ls].val;
				nd[ls].all = 1;
			}
			if (rs > 2){
				nd[rs].val = nd[u].val;
				nd[rs].sum = nd[rs].val*nd[rs].siz; // !!!
				if (nd[u].val > 0) nd[rs].le = nd[rs].ri = nd[rs].tot = nd[rs].sum;
				else nd[rs].le = nd[rs].ri = 0, nd[rs].tot = nd[rs].val;
				nd[rs].all = 1;
			}
		}
		if (nd[u].flp){
			nd[u].flp = 0;
			nd[ls].flp ^= 1; nd[rs].flp ^= 1;
			swap(nd[ls].ch[0], nd[ls].ch[1]);
			swap(nd[ls].le, nd[ls].ri);
			swap(nd[rs].ch[0], nd[rs].ch[1]);
			swap(nd[rs].le, nd[rs].ri);
		}
	}
	inline void push_up(int u){
		nd[u].siz = nd[ls].siz+nd[rs].siz+1;
		nd[u].sum = nd[ls].sum+nd[rs].sum+nd[u].val;
		nd[u].le = max(nd[ls].le, nd[ls].sum+nd[u].val+nd[rs].le);
		nd[u].ri = max(nd[rs].ri, nd[rs].sum+nd[u].val+nd[ls].ri);
		nd[u].tot = max(max(nd[ls].tot, nd[rs].tot), nd[u].val+nd[ls].ri+nd[rs].le);
	}
	void reset(int le_bd, int ri_bd){
		nd[0] = Node(0, 0); nd[0].siz = 0; nd[0].tot = -inf;
		nd[1] = Node(0, le_bd);
		nd[2] = Node(1, ri_bd); nd[1].ch[1] = 2;
		push_up(1);
		root = 1; bin.cnt = 2; bin.bcnt = 0;
	}
	inline int son(int u){
		return nd[nd[u].fa].ch[1] == u;
	}
	inline void rotate(int u){
		int v = nd[u].fa, w = nd[v].fa;
		int vs = son(u), ws = son(v);
		nd[w].ch[ws] = u;
		nd[v].fa = u;
		nd[v].ch[vs] = nd[u].ch[vs^1];
		nd[nd[u].ch[vs^1]].fa = v;
		nd[u].fa = w;
		nd[u].ch[vs^1] = v;
		push_up(v); push_up(u);
	}
	inline void splay(int u, int goal){
		while (nd[u].fa != goal){
			if (nd[nd[u].fa].fa != goal) rotate(son(u) == son(nd[u].fa) ? nd[u].fa : u);
			rotate(u);
		}
		if (goal == 0) root = u;
	}
	#undef ls
	#undef rs
}
using namespace SPLAY;
int n, m, a[N];

//void dfs(int u)
//{
//	if (!u) return;
//	push_down(u);
//	dfs(nd[u].ch[0]);
//	cout << nd[u].val << " ";
//	dfs(nd[u].ch[1]);
//}
//
//void dfs1(int u)
//{
//	if (!u) return;
//	push_down(u);
//	cout << u << " " << nd[u].ch[0] << " " << nd[u].ch[1] << " "  << nd[u].val << " " << nd[u].siz << " " << nd[u].sum << " " << nd[u].tot << " " << nd[u].le << " " << nd[u].ri << endl;
//	dfs1(nd[u].ch[0]);
//	dfs1(nd[u].ch[1]);
//}

inline void find_rnk(int root, int x)
{
	int u = root;
	while (u){
		push_down(u);
		if (nd[nd[u].ch[0]].siz >= x){u = nd[u].ch[0]; continue;}
		x -= nd[nd[u].ch[0]].siz+1;
		if (x == 0) break;
		u = nd[u].ch[1];
	}
	splay(u, nd[root].fa);
}

inline void insert(int pos, int tot, int *a)
{
	find_rnk(root, pos+2);
	find_rnk(nd[root].ch[0], pos+1);
	int u, fa = nd[root].ch[0];
	for (int i = 1; i <= tot; ++ i){
		u = bin.new_node();
		nd[fa].ch[1] = u;
		nd[u] = Node(fa, a[i]);
		fa = u;
	}
	splay(u, 0);
}

void del_dfs(int u)
{
	if (!u) return;
	bin.recyc(u);
	del_dfs(nd[u].ch[0]);
	del_dfs(nd[u].ch[1]);
}

inline void delet(int pos, int tot)
{
	find_rnk(root, pos);
	find_rnk(nd[root].ch[1], tot+1);
	del_dfs(nd[nd[root].ch[1]].ch[0]);
	nd[nd[root].ch[1]].ch[0] = 0;
	splay(nd[root].ch[1], 0);
}

inline void reverse(int pos, int tot)
{
	find_rnk(root, pos);
	find_rnk(nd[root].ch[1], tot+1);
	int u = nd[nd[root].ch[1]].ch[0];
	nd[u].flp ^= 1;
	swap(nd[u].ch[0], nd[u].ch[1]);
	swap(nd[u].le, nd[u].ri);
	push_down(u);
	splay(u, 0);
}

inline void make_same(int pos, int tot, int c)
{
//	cout << "========================================" << endl;
//	dfs(root); cout << endl; dfs1(root); cout << endl;
//	cout << "========================================" << endl;
	find_rnk(root, pos);
	find_rnk(nd[root].ch[1], tot+1);
//	cout << "========================================" << endl;
//	dfs(root); cout << endl;dfs1(root); cout << endl;
//	cout << "========================================" << endl;
	int u = nd[nd[root].ch[1]].ch[0];
	nd[u].all = 1; nd[u].val = c; nd[u].sum = c*nd[u].siz;
	if (c > 0) nd[u].le = nd[u].ri = nd[u].tot = nd[u].sum;
	else nd[u].le = nd[u].ri = 0, nd[u].tot = c;
	push_down(u);
//	cout << "========================================" << endl;
//	dfs(root); cout << endl;dfs1(root); cout << endl;
//	cout << "========================================" << endl;
	splay(u, 0);
}

inline int get_sum(int pos, int tot)
{
	find_rnk(root, pos);
	find_rnk(nd[root].ch[1], tot+1);
//	cout << "========================================" << endl;
//	dfs1(nd[nd[root].ch[1]].ch[0]); cout << endl;
//	cout << "========================================" << endl;
	return nd[nd[nd[root].ch[1]].ch[0]].sum;
}

int main()
{
//	freopen("t.in", "r", stdin);
//	freopen("t.out", "w", stdout);
	reset(-inf, -inf);
	n = read(); m = read();
	for (int i = 1; i <= n; ++ i) a[i] = read();
	insert(0, n, a);
	for (; m--; ){
		char opt[10]; int pos, tot, x;
		scanf("%s", opt);
		if (opt[2] == 'X') printf("%d\n", nd[root].tot);
		else {
			pos = read(); tot = read();
			if (opt[0] == 'G') printf("%d\n", get_sum(pos, tot));
			else if (opt[0] == 'R') reverse(pos, tot);
			else if (opt[2] == 'K') x = read(), make_same(pos, tot, x);
			else if (opt[0] == 'D') delet(pos, tot);
			else if (opt[0] == 'I'){
				for (int i = 1; i <= tot; ++ i) a[i] = read();
				insert(pos, tot, a);
			}
		}
//		cout << "---------------------------------------" << endl;
//		dfs(root); cout << endl;
//		dfs1(root);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值