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最近正在实现,因为一些特殊的原因没能在今天完成有点可惜

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

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

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

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

  • 相关阅读:
    java 的 线程池应用和实践
    拦截信息短信息并转发到指定手机
    分享 UC优视 的android程序员面试题
    解释通讯协议中的xml
    设计模式工厂模式
    MongoDB基础教程系列第一篇 进入MongoDB世界
    Docx组件读写Word文档介绍
    [转]Oracle数据库逻辑增量备份之exp/imp
    JSON文件读取
    JAVA综合--如何掌握JDK1.5枚举类型[转]
  • 原文地址:https://www.cnblogs.com/johnsonyip/p/4338152.html
Copyright © 2011-2022 走看看