zoukankan      html  css  js  c++  java
  • 【luogu P5055】【模板】可持久化文艺平衡树

    【模板】可持久化文艺平衡树

    题目链接:luogu P5055

    题目大意

    要你维护插入,删除,区间翻转,区间求和。
    但要求可持续化,即每次操作在一个历史版本上进行,且会产生一个新的历史版本

    思路

    看到题目都是可持续化平衡树了。

    直接上 splay,这题要多搞一个 down。
    down 交换左右儿子之前要复制左右儿子。

    然后其他的就跟 可持久化平衡树 是差不多的了。

    代码

    #include<queue>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define ll long long
    
    using namespace std;
    
    int n, rt[200001], bb, op, x, y, tot;
    int ls[200001 << 7], rs[200001 << 7], yj[200001 << 7], sz[200001 << 7];
    bool turn[200001 << 7];
    ll sum[200001 << 7], lastans, val[200001 << 7];
    
    int newpoint(ll num) {
    	int re = ++tot;
    	ls[re] = rs[re] = turn[re] = 0;
    	val[re] = num;
    	sum[re] = num;
    	yj[re] = rand();
    	sz[re] = 1;
    	return re;
    }
    
    int copypoint(int pl) {
    	int re = ++tot;
    	ls[re] = ls[pl];
    	rs[re] = rs[pl];
    	val[re] = val[pl];
    	sum[re] = sum[pl];
    	yj[re] = yj[pl];
    	turn[re] = turn[pl];
    	sz[re] = sz[pl];
    	return re;
    }
    
    void up(int now) {
    	sz[now] = sz[ls[now]] + sz[rs[now]] + 1;
    	sum[now] = sum[ls[now]] + sum[rs[now]] + val[now];
    }
    
    void down(int now) {
    	if (turn[now]) {
    		if (ls[now]) ls[now] = copypoint(ls[now]);//记得翻转前左右儿子要复制
    		if (rs[now]) rs[now] = copypoint(rs[now]);
    		swap(ls[now], rs[now]);
    		if (ls[now]) turn[ls[now]] ^= 1;
    		if (rs[now]) turn[rs[now]] ^= 1;
    		turn[now] ^= 1;
    	}
    } 
    
    pair <int, int> split_rnk(int now, int rnk) {
    	if (!now) return make_pair(0, 0);
    	if (!rnk) return make_pair(0, copypoint(now));
    	
    	down(now);
    	
    	pair <int, int> re;
    	if (rnk <= sz[ls[now]]) {
    		int noww = copypoint(now);
    		re = split_rnk(ls[noww], rnk);
    		ls[noww] = re.second;
    		up(noww);
    		re.second = noww;
    	}
    	else {
    		int noww = copypoint(now);
    		re = split_rnk(rs[noww], rnk - sz[ls[now]] - 1);
    		rs[noww] = re.first;
    		up(noww);
    		re.first = noww;
    	}
    	
    	return re;
    }
    
    int merge(int x, int y) {
    	if (x) down(x);
    	if (y) down(y);
    	if (!x) return y;
    	if (!y) return x;
    	
    	if (yj[x] < yj[y]) {
    		int xx = copypoint(x);
    		rs[xx] = merge(rs[xx], y);
    		up(xx);
    		return xx;
    	}
    	else {
    		int yy = copypoint(y);
    		ls[yy] = merge(x, ls[yy]);
    		up(yy);
    		return yy;
    	}
    }
    
    void insert(int bb, int pl, int num) {
    	pair <int, int> x = split_rnk(rt[bb], pl);
    	int y = newpoint(num);
    	rt[bb] = merge(x.first, merge(y, x.second));
    }
    
    void delete_(int bb, int pl) {
    	pair <int, int> x = split_rnk(rt[bb], pl - 1);
    	pair <int, int> y = split_rnk(x.second, 1);
    	rt[bb] = merge(x.first, y.second);
    }
    
    void turn_(int bb, int l, int r) {
    	pair <int, int> x = split_rnk(rt[bb], l - 1);
    	pair <int, int> y = split_rnk(x.second, r - l + 1);
    	
    	turn[y.first] ^= 1;
    	
    	rt[bb] = merge(merge(x.first, y.first), y.second);
    }
    
    ll get_sum(int bb, int l, int r) {
    	pair <int, int> x = split_rnk(rt[bb], l - 1);
    	pair <int, int> y = split_rnk(x.second, r - l + 1);
    	return sum[y.first];
    }
    
    int main() {
    	srand(19491001);
    	
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++) {
    		scanf("%d %d", &bb, &op);
    		rt[i] = rt[bb];
    		if (op == 1) {
    			scanf("%d %d", &x, &y);
    			x ^= lastans; y ^= lastans;
    			insert(i, x, y); 
    			continue;
    		}
    		if (op == 2) {
    			scanf("%d", &x);
    			x ^= lastans;
    			delete_(i, x);
    			continue;
    		}
    		if (op == 3) {
    			scanf("%d %d", &x, &y);
    			x ^= lastans;
    			y ^= lastans;
    			turn_(i, x, y);
    			continue;
    		}
    		if (op == 4) {
    			scanf("%d %d", &x, &y);
    			x ^= lastans;
    			y ^= lastans;
    			lastans = get_sum(i, x, y);
    			printf("%lld
    ", lastans);
    		}
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    php程序去除文件 bom头
    类继承接口后,实现接口的方法
    virtual和abstract的使用场景分别是什么?待更新。
    get请求和post请求的总结
    ES6新语法,持续更新
    display:flex中的不懂的问题,待处理
    css相邻兄弟选择器(+),伪类(:hover),伪元素(::after)
    HTML中的input的type类型
    命令行打开程序的集合
    sqlserver 常用的语句
  • 原文地址:https://www.cnblogs.com/Sakura-TJH/p/luogu_P5055.html
Copyright © 2011-2022 走看看