zoukankan      html  css  js  c++  java
  • 【模板】普通平衡树

    题面

    题解

    过年啦!!!

    在这红红火火的日子里,肯定要写(color{red}{mathrm{Red}};color{black}{mathrm{Black}};tree)来愉悦身心啊

    然鹅出现了一些小尴尬

    虽然代码行数跟(mathrm{s(p)lay})没法比肯定是大括号太占地方了

    但是:

    指针版的(mathrm{s(p)lay})https://www.luogu.org/recordnew/show/8772600

    (color{red}{mathrm{Red}};color{black}{mathrm{Black}};tree)https://www.luogu.org/recordnew/show/16079271

    代码长度比较起来,红黑树胜!!!

    ha???

    速度当然也是吊着打啦

    从此红黑树走进了每个OIer的电脑

    代码

    我这能算突破红黑树代码长度极限了吗(mathrm{QwQ})

    #include<cstdio>
    #include<cstring>
    #include<climits>
    #define RG register
    
    inline int read()
    {
    	int data = 0, w = 1;
    	char ch = getchar();
    	while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    	if(ch == '-') w = -1, ch = getchar();
    	while(ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
    	return data * w;
    }
    
    const int maxn(1e6 + 10);
    int son[2][maxn], fa[maxn], size[maxn], cur;
    int cnt[maxn], col[maxn], val[maxn], root;
    inline void newNode(int k, int c, int f)
    {
    	int x = ++cur;
    	fa[x] = f, size[x] = cnt[x] = 1;
    	val[x] = k, col[x] = c;
    }
    
    inline void update(int x) { size[x] = size[son[0][x]] + cnt[x] + size[son[1][x]]; }
    inline void rotate(int x, int r)
    {
    	int y = son[!r][x]; son[!r][x] = son[r][y];
    	if(son[r][y]) fa[son[r][y]] = x;
    	fa[y] = fa[x]; if(!fa[x]) root = y;
    	else son[x == son[1][fa[x]]][fa[x]] = y;
    	son[r][y] = x, fa[x] = y, size[y] = size[x];
    	update(x);
    }
    
    inline void transplant(int to, int from)
    {
    	fa[from] = fa[to]; if(!fa[to]) root = from;
    	else son[to == son[1][fa[to]]][fa[to]] = from;
    }
    
    int findMin(int x) { while(son[0][x]) x = son[0][x]; return x; }
    void insertFixUp(int z)
    {
    	while(col[fa[z]])
    	{
    		int f = fa[z], g = fa[f], l = f == son[0][g], y = son[l][g];
    		if(col[y]) col[y] = col[f] = 0, col[z = g] = 1;
    		else
    		{
    			if(z == son[l][f]) z = f, rotate(z, !l);
    			col[fa[z]] = 0, col[fa[fa[z]]] = 1; rotate(g, l);
    		}
    	}
    	col[root] = 0;
    }
    
    void insert(int k)
    {
    	int x = root, y = 0;
    	while(x)
    	{
    		++size[y = x]; if(val[x] == k) return (void) (++cnt[x]);
    		x = son[val[x] < k][x];
    	}
    	newNode(k, 1, y);
    	if(!y) root = cur; else son[val[y] < k][y] = cur;
    	insertFixUp(cur);
    }
    
    void delFixUp(int x)
    {
    	while(x != root && (!col[x]))
    	{
    		int l = x == son[0][fa[x]], f = fa[x], w = son[l][f];
    		if(col[w])
    		{
    			col[f] = 1, col[w] = 0;
    			rotate(f, !l); w = son[l][f];
    		}
    		if((!col[son[0][w]]) && (!col[son[1][w]])) col[w] = 0, x = fa[x];
    		else
    		{
    			if(!col[son[l][w]])
    				col[w] = 1, col[son[!l][w]] = 0,
    				rotate(w, l), w = son[l][f];
    			col[w] = col[f], col[f] = 0; col[son[l][w]] = 0;
    			rotate(fa[w], !l); x = root;
    		}
    	}
    	col[x] = 0;
    }
    
    void erase(int k)
    {
    	int z = root, w = 0;
    	while(z)
    	{
    		--size[w = z]; if(k == val[z]) break;
    		z = son[val[z] < k][z];
    	}
    	if(z)
    	{
    		if(cnt[z] > 1) return (void) (--cnt[z]);
    		int y = z, x, oldc = col[y];
    		if(!son[0][z]) x = son[1][z], transplant(z, son[1][z]);
    		else if(!son[1][z]) x = son[0][z], transplant(z, son[0][z]);
    		else
    		{
    			y = findMin(son[1][z]); oldc = col[y], x = son[1][y];
    			if(fa[y] == z) fa[x] = y;
    			else
    			{
    				int tmpy = y;
    				while(tmpy != z) size[tmpy] -= cnt[y], tmpy = fa[tmpy];
    				transplant(y, son[1][y]); son[1][y] = son[1][z];
    				fa[son[1][y]] = y;
    			}
    			transplant(z, y); son[0][y] = son[0][z];
    			fa[son[0][y]] = y, col[y] = col[z]; update(y);
    		}
    		if(!oldc) delFixUp(x);
    	}
    	else while(w) ++size[w], w = fa[w];
    }
    
    inline int cmp(int x, int k) { return (val[x] < k) ? 0 : (val[x] ^ k ? 1 : -1); }
    int suc(int k, int b)
    {
    	int x = root, p = 0;
    	while(x) if(cmp(x, k) == b) p = x, x = son[!b][x];
    	else x = son[b][x];
    	return val[p];
    }
    
    int k_th(int k)
    {
    	int x = root;
    	while(x)
    	{
    		int l = son[0][x], r = son[1][x];
    		if(size[l] + 1 <= k && size[l] + cnt[x] >= k) return val[x];
    		else if(size[l] + cnt[x] < k) k -= size[l] + cnt[x], x = r; else x = l;
    	}
    	return INT_MAX;
    }
    
    inline int rank(int r)
    {
    	int x = root, ret = 0;
    	while(x)
    	{
    		if(val[x] < r) ret += size[son[0][x]] + cnt[x], x = son[1][x];
    		else x = son[0][x];
    	}
    	return ret + 1;
    }
    
    int main()
    {
    	int n = read();
    	while(n--)
    	{
    		int opt = read(), x = read();
    		switch(opt)
    		{
    			case 1: insert(x); break;
    			case 2: erase(x); break;
    			case 3: printf("%d
    ", rank(x)); break;
    			case 4: printf("%d
    ", k_th(x)); break;
    			case 5: case 6: printf("%d
    ", suc(x, opt - 5)); break;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    全网最贴心webpack系列教程和配套代码
    webpack4 系列教程(十五):开发模式与webpack-dev-server
    CSS元素显示模式
    CSS符合选择器
    Emmet语法
    CSS引入方式
    CSS文本属性
    CSS字体属性
    CSS语法规范一
    案例
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/10353748.html
Copyright © 2011-2022 走看看