zoukankan      html  css  js  c++  java
  • 替罪羊树

    替罪羊树

    暴力重构的思想,如果树不够平衡,那么就拍扁重构即可

    和 treap 的操作大致都一样就是了,但常数挺小的,可以卡常使用

    const int N = 2005000;
    struct node {
    	int ls, rs, siz, sum;
    	int key, val;
    	#define key(k) p[k].key
    	#define val(k) p[k].val
    	#define ls(k) p[k].ls
    	#define rs(k) p[k].rs
    	#define siz(k) p[k].siz
    	#define sum(k) p[k].sum
    }p[N];
    int rt, cnt;
    const double A = 0.8;
    bool judge(int k) {
    	return val(k) && A * siz(k) < max(siz(ls(k)), siz(rs(k)));
    }
    
    void update(int k) {
    	siz(k) = siz(ls(k)) + siz(rs(k)) + (val(k) ? 1 : 0);
    	sum(k) = sum(ls(k)) + sum(rs(k)) + val(k);
    }
    
    int st[N], tp;
    void pia(int k) {
    	if (ls(k)) pia(ls(k));
    	if (val(k)) st[++tp] = k;
    	if (rs(k)) pia(rs(k));
    	return;
    }
    
    int rebuild(int l, int r) {
    	if (l > r) return 0;
    	int mid = (l + r) >> 1;
    	ls(st[mid]) = rebuild(l, mid - 1);
    	rs(st[mid]) = rebuild(mid + 1, r);
    	return update(st[mid]), st[mid];
    }
    int maintain(int p) {
    	return tp = 0, pia(p), rebuild(1, tp);
    }
    void insert(int &x, int val) {
    	if (!x) {
    		x = ++cnt, key(x) = val;
    		val(x) = siz(x) = sum(x) = 1;
    	}
    	else {
    		if (key(x) == val) val(x)++;
    		else if (val < key(x)) insert(ls(x), val);
    		else insert(rs(x), val);
    		update(x); judge(x) && (x = maintain(x));
    	}
    }
    void del(int &x, int val) {
    	sum(x)--;
    	if (key(x) == val) val(x)--;
    	else key(x) > val ? del(ls(x), val) : del(rs(x), val);
    	update(x), judge(x) && (x = maintain(x));
    }
    int rkup(int x, int k) {
    	int nw = 0;
    	while (1) {
    		if (!x) return nw;
    		if (key(x) == k) return nw + sum(ls(x)) + val(x);
    		if (key(x) <= k) nw += sum(ls(x)) + val(x), x = rs(x);
    		else x = ls(x);
    	}
    }
    int rkdw(int x, int k) {
    	int nw = 1;
    	while (1) {
    		if (!x) return nw;
    		if (key(x) == k) return nw + sum(ls(x));
    		if (key(x) <= k) nw += sum(ls(x)) + val(x), x = rs(x);
    		else x = ls(x);
    	}
    }
    
    int get(int k) {
    	int x = rt;
    	while (1) {
    		if (sum(ls(x)) >= k) x = ls(x);
    		else if (sum(ls(x)) + val(x) >= k) return key(x);
    		else k -= sum(ls(x)) + val(x), x = rs(x);
    	}
    	return 1;
    }
    
    int n, t, x, m, las, ans;
    int main() {
    	for (read(n), read(m); n; n--) 
    		read(x), insert(rt, x);
    	for (; m; m--) {
    		read(t), read(x), x ^= las;
    		if (t == 1) insert(rt, x);
    		else if (t == 2) del(rt, x);
    		else if (t == 3) las = rkdw(rt, x);
    		else if (t == 4) las = get(x);
    		else if (t == 5) las = get(rkdw(rt, x) - 1);
    		else las = get(rkup(rt, x) + 1);
    		if (t >= 3) ans ^= las;
    	}
    	write(ans);
    	return 0;
    }
    
  • 相关阅读:
    浏览器事件.html
    奇数(11~99)四个一行输出.html
    JDBC系列教材 (十一)- 数据库连接池
    JDBC系列教材 (十)- 基于JDBC设计DAO的实例
    JDBC系列教材 (九)- 使用JDBC做一个ORM例子
    JDBC系列教材 (八)- 如何在JDBC中使用事务
    JDBC系列教材 (七)- 获取自增长id以及表的元数据
    JDBC系列教材 (六)- 中execute与executeUpdate的区别
    JDBC系列教材 (五)- 在JDBC中使用预编译Statement 以及它的优点
    JDBC系列教材 (四)- 在JDBC中使用ResultSet查询SQL语句
  • 原文地址:https://www.cnblogs.com/Hs-black/p/13362704.html
Copyright © 2011-2022 走看看