zoukankan      html  css  js  c++  java
  • 平衡树

    splay

    普通平衡树

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int read(void) {
    	int x = 0; bool f = 0;
    	char c = getchar();
    	for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
    	for (;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^48);
    	if (f) return -x;
    	return x;
    }
    
    const int N = 100005;
    const int INF = 0x7fffffff;
    int v[N], f[N], son[N][2];
    int cnt[N], siz[N], tot;
    int val[N], n, sz, root;
    
    inline void update(int x) {
    	siz[x] = siz[son[x][0]] + siz[son[x][1]] + cnt[x];
    }
    
    inline void rotate(int x) {
    	int y = f[x], z = f[y];;
    	int k = son[f[x]][1] == x, w = son[x][k^1];
    	son[y][k] = w, f[w] = y;
    	son[z][son[z][1] == y] = x, f[x] = z;
    	son[x][k^1] = y, f[y] = x;
    	update(y), update(x);
    }
    
    inline void splay(int x,int t) {
    	while (f[x] != t) {
    		int y = f[x], z = f[y];
    		if (z != t) {
    			if ((son[y][1] == x) ^ (son[z][1] == y)) 
    				rotate(x);
    			else rotate(y);
    		}
    		rotate(x);
    	}
    	if (t == 0) root = x;
    }
    
    inline void insert(int x) {
    	int p = root, pre = 0;
    	while (p && val[p] != x) 
    		pre = p, p = son[p][val[p] < x];
    	if (p) cnt[p]++;
    	else {
    		p = ++sz; cnt[p] = siz[p] = 1;
    		if (pre) son[pre][val[pre] < x] = p;
    		son[p][0] = son[p][1] = 0;
    		f[p] = pre, val[p] = x;
    	}
    	splay(p, 0);
    }
    
    inline void find(int x) {
    	int p = root;
    	while (son[p][val[p] < x] && val[p] != x) 
    		p = son[p][val[p] < x];
    	splay(p, 0);
    }
    
    inline int get_rk(int x) {
    	find(x);
    	return siz[son[root][0]];
    }
    
    inline int kth(int x) {
    	int p = root; x++;
    	while (true) {
    		if (son[p][0] && x <= siz[son[p][0]]) p = son[p][0];
    		else if (x > siz[son[p][0]] + cnt[p]) 
    			x -= siz[son[p][0]] + cnt[p], p = son[p][1];
    		else return val[p];
    	}
    }
    
    inline int get_pre(int x) {
    	find(x);
    	if (val[root] < x) return root;
    	int p = son[root][0];
    	while (son[p][1]) p = son[p][1];
    	return p;
    }
    
    inline int get_nxt(int x) {
    	find(x);
    	if (val[root] > x) return root;
    	int p = son[root][1];
    	while (son[p][0]) p = son[p][0];
    	return p;
    }
    
    inline void del(int x) {
    	int pre = get_pre(x), nxt = get_nxt(x);
    	splay(pre, 0), splay(nxt, root);
    	int p = son[nxt][0];
    	if (cnt[p] > 1) cnt[p]--, splay(p, 0);
    	else son[nxt][0] = 0, update(nxt), update(root);
    }
    
    
    int main() {
    	int opt, x; n = read();
    	insert(INF), insert(-INF);
    	for (int i = 1;i <= n; i++) {
    		opt = read(), x = read();
    		if (opt == 1) insert(x);
    		else if (opt == 2) del(x);
    		else if (opt == 3) printf ("%d
    ", get_rk(x));
    		else if (opt == 4) printf ("%d
    ", kth(x));
    		else if (opt == 5) printf ("%d
    ", val[get_pre(x)]);
    		else printf ("%d
    ", val[get_nxt(x)]);
    	}
    	return 0;
    }
    
    

    文艺平衡树

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    const int N = 200050;
    const int INF = 0x7fffffff;
    int read(void) {
    	int x = 0; bool f = 0;
    	char c = getchar(); 
    	for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
    	for (;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^48);
    	return f ? -x : x;
    }
    
    int val[N], son[N][2];
    int tag[N], f[N], n, sz;
    int siz[N], rt;
    
    void update(int x) {
    	siz[x] = siz[son[x][1]] + siz[son[x][0]] + 1;
    }
    
    void spread(int x) {
    	if (!tag[x]) return;
    	swap(son[x][0], son[x][1]);
    	if (son[x][0]) tag[son[x][0]] ^= 1;
    	if (son[x][1]) tag[son[x][1]] ^= 1;
    	tag[x] = 0;
    }
    
    int kth(int k) {
    	int x = rt;
    	while (true) {
    		spread(x);
    		if (siz[son[x][0]] >= k) x = son[x][0];
    		else if (siz[son[x][0]] + 1 == k) return x;
    		else k -= siz[son[x][0]] + 1, x = son[x][1];
    	}
    }
    
    void rotate(int x) {
    	int y = f[x], z = f[y];
    	int k = son[y][1] == x, w = son[x][k^1];
    	son[y][k] = w, f[w] = y;
    	f[y] = x, son[x][k^1] = y;
    	son[z][son[z][1]==y] = x, f[x] = z;
    	update(y), update(x);
    }
    
    void splay(int x,int t) {
    	while (f[x] != t) {
    		int y = f[x], z = f[y];
    		if (z != t) {
    			if ((son[z][1]==y)^(son[y][1]==x))
    				rotate(x);
    			else rotate(y);
    		}
    		rotate(x);
    	}
    	if (t == 0) rt = x;
    }
    
    void insert(int x) {
    	int p = rt, pre = 0;
    	while (p) 
    		pre = p, p = son[p][val[p] < x];
    	p = ++sz;
    	if (pre) son[pre][val[pre]<x] = p;
    	siz[p] = 1, son[p][0] = son[p][1] = 0;
    	f[p] = pre, val[p] = x;
    	splay(p, 0);
    }
    
    void rec(int x) {
    	spread(x);
    	if (son[x][0]) rec(son[x][0]);
    	if (val[x] > 1 && val[x] < n + 2) 
    	printf ("%d ", val[x]-1);
    	if (son[x][1]) rec(son[x][1]);
    }
    
    inline void work(int l,int r) {
    	l = kth(l), r = kth(r+2);
    	splay(l, 0); splay(r, rt);
    	tag[son[son[rt][1]][0]] ^= 1;
    }
    
    int m, l, r;
    int main() {
    	n = read(), m = read();
    	for (int i = 1;i <= n + 2; i++) 
    	insert(i);
    	while (m--) {
    		l = read(), r = read();
    		work(l, r);
    	}
    	rec(rt);
    	cout << endl;
    	return 0;
    }
    

    fhq板子(代码正确且风格易懂)

    洛谷P3369

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<ctime>
    #include<cstdlib>
    using namespace std;
    const int N = 105000;
    int val[N], son[N][2];
    int rnd[N], tot, n;
    int siz[N], root, a, p, x, y, z;
    inline void update(int x) {
    	siz[x] = siz[son[x][1]] + siz[son[x][0]] + 1;
    }
    inline int build(int x) {
    	siz[++tot] = 1, rnd[tot] = rand();
    	val[tot] = x; return tot;
    }
    int merge(int x,int y) {
    	if (!x || !y) return x + y;
    	if (rnd[x] < rnd[y]) {
    		son[x][1] = merge(son[x][1], y);
    		update(x); return x;
    	}
    	son[y][0] = merge(x, son[y][0]);
    	update(y); return y;
    }
    void split(int now,int k,int &x,int &y) {
    	if (!now) x = y = 0;
    	else {
    		if (val[now] <= k) x = now, split(son[x][1], k, son[x][1], y);
    		else y = now, split(son[y][0], k, x, son[y][0]);
    		update(now);
    	}
    }
    
    inline int kth(int now, int k) {
    	while (1) {
    		if (k <= siz[son[now][0]]) now = son[now][0];
    		else if (k == siz[son[now][0]] + 1) return now;
    		else k -= siz[son[now][0]] + 1, now = son[now][1];
    	}
    }
    template <typename T> 
    void read(T &x) {
    	x = 0; int f = 1;char c = getchar();
    	while (!isdigit(c)) { if (c == '-') f = -1; c = getchar();}
    	while (isdigit(c)) { x = (x << 3)+(x << 1) + c-'0'; c = getchar();}
    	x *= f;
    }	
    int main() {
    	srand(time(0));
    	read(n);
    	for (int i = 1;i <= n; i++) {
    		read(p), read(a);
    		if (p == 1) {
    			split(root, a, x, y);
    			root = merge(merge(x, build(a)), y);
    		}
    		else if (p == 2) {
    			split(root, a, x, y);
    			split(x, a-1, x, z);
    			z = merge(son[z][0], son[z][1]);
    			root = merge(merge(x, z), y);
    		}
    		else if (p == 3) {
    			split(root, a-1, x, y);
    			printf ("%d
    ", siz[x] + 1);
    			root = merge(x, y);
    		}
    		else if (p == 4) printf ("%d
    ", val[kth(root, a)]);
    		else if (p == 5) {
    			split(root, a-1, x, y);
    			printf ("%d
    ", val[kth(x, siz[x])]);
    			root = merge(x, y);
    		}
    		else {
    			split(root, a, x, y);
    			printf ("%d
    ", val[kth(y, 1)]);
    			root = merge(x, y);
    		}
    	}
    	return 0;
    }
    

    洛谷P3391

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<ctime>
    using namespace std;
    const int N = 100050;
    int rnd[N], siz[N];
    int cnt, n, l, r;
    int tag[N], son[N][2];
    int val[N], root, x, y, z;
    inline int build(int x) {
    	siz[++cnt] = 1, val[cnt] = x;
    	rnd[cnt] = rand(); return cnt;
    }
    inline void update(int x) {
    	siz[x] = siz[son[x][1]] + siz[son[x][0]] + 1;
    }
    void spread(int x) {
    	if (tag[x]) {
    		swap(son[x][0], son[x][1]);
    		if (son[x][0]) tag[son[x][0]] ^= 1;
    		if (son[x][1]) tag[son[x][1]] ^= 1;
    		tag[x] = 0;
    	}
    }
    void split(int now,int k,int &x,int &y) {
    	if (!now) x = y = 0;
    	else {
    		spread(now);
    		if (siz[son[now][0]] < k) x = now, split(son[x][1], k - siz[son[now][0]] - 1, son[x][1], y);
    		else y = now, split(son[y][0], k, x, son[y][0]);
    		update(now);
    	}
    }
    int merge(int x,int y) {
    	if(!x || !y) return x + y;
    	if (rnd[x] < rnd[y]) {
    		spread(x);
    		son[x][1] = merge(son[x][1], y);
    		update(x); return x;
    	}
    	spread(y);
    	son[y][0] = merge(x, son[y][0]);
    	update(y); return y;
    }
    template <typename T> 
    void read(T &x) {
    	x = 0; int f = 1;char c = getchar();
    	while (!isdigit(c)) { if (c == '-') f = -1; c = getchar();}
    	while (isdigit(c)) { x = (x << 3)+(x << 1) + c-'0'; c = getchar();}
    	x *= f;
    }	
    int m;
    void res(int x) {
    	if (!x) return;
    	spread(x);
    	res(son[x][0]);
    	printf ("%d ", val[x]);
    	res(son[x][1]);
    }
    int main() {
    	read(n), read(m);
    	for (int i = 1;i <= n; i++) root = merge(root, build(i));
    	while (m--) {
    		read(l), read(r);
    		split(root, l - 1, x, y);
    		split(y, r - l+ 1, y, z);
    		tag[y] ^= 1;
    		root = merge(merge(x, y), z);
    	}
    	res(root);
    	return 0;
    }
    

    可持久化平衡树
    p3835

    #include<iostream>
    #include<cstdio>
    #include<ctime>
    #include<cstdlib>
    #include<cstring>
    using namespace std;
    const int N = 500500 * 50;
    const int INF = 2147483647;
    int T[N], val[N], rnd[N];
    int siz[N], son[N][2];
    int cnt; 
    
    template <typename T> 
    void read(T &x) {
    	x = 0; int f = 1;char c = getchar();
    	while (!isdigit(c)) { if (c == '-') f = -1; c = getchar();}
    	while (isdigit(c)) { x = (x << 3)+(x << 1) + c-'0'; c = getchar();}
    	x *= f;
    }
    
    inline void update(int x) {
    	siz[x] = siz[son[x][0]] + siz[son[x][1]] + 1;
    }
    
    inline void cpy(int x,int y) {
    	siz[x] = siz[y], son[x][1] = son[y][1];
    	son[x][0] = son[y][0];
    	val[x] = val[y], rnd[x] = rnd[y];
    }
    inline int build(int x) {
    	val[++cnt] = x, siz[cnt] = 1;
    	rnd[cnt] = rand(); return cnt;
    }
    	
    void split(int now,int k,int &x,int &y) {
    	if (!now) x = y = 0;
    	else {
    		if (val[now] <= k) {
    			x = ++cnt, cpy(x, now), split(son[x][1], k, son[x][1], y);
    			update(x);
    		}
    		else {
    			y = ++cnt, cpy(y, now), split(son[y][0], k, x, son[y][0]);
    			update(y);
    		}
    	}
    }
    
    int merge(int x,int y) {
    	if (!x || !y) return x + y;
    	if (rnd[x] < rnd[y]) {
    		int p = ++cnt; cpy(p, x);
    		son[p][1] = merge(son[p][1], y); 
    		update(p); return p;
    	}
    	int p = ++cnt; cpy(p, y);
    	son[p][0] = merge(x, son[p][0]); 
    	update(p); return p;
    } 
    
    int kth(int now,int x) {
    	while (1) {
    		if (siz[son[now][0]] >= x) now = son[now][0];
    		else if (siz[son[now][0]] + 1 == x) return now;
    		else x -= siz[son[now][0]] + 1, now = son[now][1];
    	}
    }
    
    int n, x, y, z;
    int op, P, a;
    int main() {
    	srand(20040202);
    	read(n);
    	for (int i = 1;i <= n; i++) {
    		read(P), read(op), read(a);
    		T[i] = T[P];
    		if (op == 1) {
    			split(T[i], a, x, y);
    			T[i] = merge(merge(x, build(a)), y);
    		}
    		else if (op == 2) {
    			split(T[i], a, x, z);
    			split(x, a-1, x, y);
    			y = merge(son[y][0], son[y][1]);
    			T[i] = merge(merge(x, y), z);
    		}
    		else if (op == 3) {
    			split(T[i], a-1, x, y);
    			printf ("%d
    ", siz[x] + 1);
    			T[i] = merge(x, y);
    		}
    		else if (op == 4) printf ("%d
    ", val[kth(T[i], a)]);
    		else if (op == 5) {
    			split(T[i], a-1, x, y);
    			if (siz[x] == 0) printf ("%d
    ", -INF);
    			else printf ("%d
    ", val[kth(x, siz[x])]);
    			T[i] = merge(x, y);
    		}
    		else if (op == 6) {
    			split(T[i], a, x, y);
    			if (siz[y] == 0) printf ("%d
    ", INF);
    			else printf ("%d
    ", val[kth(y, 1)]);
    			T[i] = merge(x, y);
    		}
    	}
    	return 0;
    }	
    
  • 相关阅读:
    logstash日志分析的配置和使用
    实现跨浏览器html5表单验证
    CSS常见居中讨论
    centos7 初始化脚本
    elasticsearch+logstash+redis+kibana 实时分析nginx日志
    centos7 系统优化
    cAdvisor+InfluxDB+Grafana 监控Docker
    Docker三剑客之Docker Swarm
    Docker三剑客之常用命令
    Docker三剑客之Docker Compose
  • 原文地址:https://www.cnblogs.com/Hs-black/p/11630876.html
Copyright © 2011-2022 走看看