• 【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;
    }
    
  • 相关阅读:
    分享一道关于类、实例加载和初始化顺序的基础面试题
    IDEA部署 java Web项目 常见配置
    jsp和servlet开发过程中参数传递乱码问题总结
    Java String引起的常量池、String类型传参、“==”、“equals”、“hashCode”问题 细节分析
    利用反射创建实例强制转换为接口失败小结
    oracle与sqlserver的十大区别
    js闭包的用途 【转】
    实体框架EF笔记
    利用存储过程进行分页
    关于ASP.NET运行机制原理。。。个人总结
  • 原文地址:https://www.cnblogs.com/Sakura-TJH/p/luogu_P5055.html
Copyright © 2020-2023  润新知