zoukankan      html  css  js  c++  java
  • Splay模板

    此模板对于信息竞赛已经够用了,但是没有考虑建两棵或以上的Splay的情况,如果是需要实现可以稍微改一下

    纪念一下曾经的Notonlysuccess,我从那里学会了线段树和splay,可惜现在好像上不去了……

    这段代码作为模板也挺不错的,自我感觉可扩展性良好

    #include <cstdio>
    #define MAXN 100010
    using namespace std;
    
    int n;
    int root, node;
    int parent[MAXN], child[MAXN][2];
    int weight[MAXN], size[MAXN], count[MAXN];
    int trash[MAXN], top;
    
    inline void update(int x) {
    	size[x] = count[x] + size[child[x][0]] + size[child[x][1]];
    }
    
    inline void rotate(int x) {
    	int y = parent[x]; bool dir = child[y][0] == x;
    	if (child[y][!dir] = child[x][dir]) parent[child[x][dir]] = y;
    	if (parent[x] = parent[y]) child[parent[y]][child[parent[y]][1] == y] = x;
    	update(child[x][dir] = y); parent[y] = x;
    }
    
    inline void splay(int x, int goal) {
    	for (int y = parent[x]; y ^ goal; rotate(x), y = parent[x])
    		if (parent[y] ^ goal) rotate(child[y][child[parent[y]][0] == y] ? x : y);
    	update(x); if (!goal) root = x;
    }
    
    inline void new_node(int w, int &x, int pre) {
    	if (top) x = trash[--top]; else x = ++node;
    	child[x][0] = child[x][1] = 0;
    	count[x] = size[x] = 1;
    	parent[x] = pre;
    	weight[x] = w;
    }
    
    inline void insert(int value) {
    	int x = root;
    	if (size[x]) {
    		int y = parent[x];
    		while (x && value ^ weight[x])
    			++size[x], y = x, x = child[x][value > weight[x]];
    		bool dir = value > weight[y];
    		if (x) ++size[x], ++count[x];
    		else new_node(value, child[y][dir], y);
    	} else new_node(value, root, 0);
    }
    
    inline void remove(int value) {
    	int x = root;
    	while (x && value ^ weight[x])
    		x = child[x][value > weight[x]];
    	if (!x) return;
    	if (count[x] == 1) {
    		bool f = !child[x][0];
    		int y = child[x][f] ? child[x][f] : x;
    		while (child[y][!f]) y = child[y][!f];
    		bool b = child[parent[y]][1] == y;
    		if (parent[y]) child[parent[y]][b] = child[y][f];
    		if (child[y][f]) parent[child[y][f]] = parent[y];
    		weight[x] = weight[y]; count[x] = count[y];
    		for (count[x = y] = 0; x; x = parent[x]) update(x);
    		if (root == (trash[top++] = y)) root = 0;
    	} else for (--count[x]; x; x = parent[x]) --size[x];
    }
    
    inline int search(int w) {
    	int x = root;
    	while (x && w ^ weight[x])
    		x = child[x][w > weight[x]];
    	splay(x, root); return x;
    }
    
    inline int rank(int w) {
    	int x = root, ret = 0;
    	while (x && w ^ weight[x])
    		if (w < weight[x]) x = child[x][0];
    		else ret += count[x] + size[child[x][0]], x = child[x][1];
    	return ret + size[child[x][0]] + 1;
    }
    
    inline int find_kth(int k) {
    	if (k < 0 || k > size[root]) return 0;
    	int x = root;
    	while (k <= size[child[x][0]] || k > size[child[x][0]] + count[x])
    		if (k <= size[child[x][0]]) x = child[x][0];
    		else k -= size[child[x][0]] + count[x], x = child[x][1];
    	splay(x, 0); return x;
    }
    
    inline int prev(int w) {
    	int x = root, y = 0;
    	while (x)
    		if (w <= weight[x]) x = child[x][0];
    		else y = x, x = child[x][1];
    	if (y) splay(y, 0); return y;
    }
    
    inline int succ(int w) {
    	int x = root, y = 0;
    	while (x)
    		if (w >= weight[x]) x = child[x][1];
    		else y = x, x = child[x][0];
    	if (y) splay(y, 0); return y;
    }
    
    int main() {
    	for (scanf("%d", &n); n; --n) {
    		int op, x; scanf("%d%d", &op, &x);
    		switch (op) {
    			case 1: insert(x); break;
    			case 2: remove(x); break;
    			case 3: printf("%d
    ", rank(x)); break;
    			case 4: printf("%d
    ", weight[find_kth(x)]); break;
    			case 5: printf("%d
    ", weight[prev(x)]); break;
    			case 6: printf("%d
    ", weight[succ(x)]); break;
    		}
    	}
    	return 0;
    }
    

    这其实是BZOJ3224 Tyvj1728 普通平衡树的题解

    此题是极好的模板题,任何二叉搜索树都可以用它来检测代码的正确性

    对了那个类的Splay最近正在实现,因为一些特殊的原因没能在今天完成有点可惜

    大概明天就可以搞好,会发上来的

    实在是很累,先休息一晚上吧……到时候再推荐一下平衡树的入门题好了

    很可惜,身边的所有人都告诉我要以学业为重,这个博客可能无法持续更新

    真的,我觉得自己曾经的梦想幻灭,心很痛。

  • 相关阅读:
    Combine 框架,从0到1 —— 4.在 Combine 中使用计时器
    Combine 框架,从0到1 —— 4.在 Combine 中使用通知
    Combine 框架,从0到1 —— 3.使用 Subscriber 控制发布速度
    Combine 框架,从0到1 —— 2.通过 ConnectablePublisher 控制何时发布
    使用 Swift Package Manager 集成依赖库
    iOS 高效灵活地配置可复用视图组件的主题
    构建个人博客网站(基于Python Flask)
    Swift dynamic关键字
    Swift @objcMembers
    仅用递归函数操作逆序一个栈(Swift 4)
  • 原文地址:https://www.cnblogs.com/johnsonyip/p/4338152.html
Copyright © 2011-2022 走看看