• 可持续化线段树


    可持续化线段树,也叫主席树,很久以前【也没多久】写了一篇求区间第k大的,那时候理解不深,现在再写一个加深理解

    可持续化,具体来说就是可以访问历史版本,以实现跨时间的操作。

    怎么实现呢?
    试想我们修改线段树的时候,修改前是旧版本,修改后是新版本,想想新版本和旧版本有什么区别?
    区别就在于从根节点到被修改点的路径上的点改变了,其他的点是不变的

    那么这个时候我们新建一个根节点,对于不变的儿子指向旧版本的儿子,对于有变化的儿子就新建一个节点
    这样一来我们有每一个时刻的根节点,就可以访问到每个时刻的线段树
    空间会不会暴呢?
    每条路径只有logn个点,m次修改我们只多了mlogn个点,可以承受
    但实在空间卡得很紧时就要用指针了

    比如洛谷P3931

    下面给出指针版题解代码【并非完全是普遍的写法,由题简化】:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define fo(i,x,y) for (int i = (x); i <= (y); i++)
    #define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
    using namespace std;
    const int maxn = 1000005,maxm = 10000005,INF = 1000000000;
    
    inline int read(){
    	int out = 0,flag = 1;char c = getchar();
    	while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}
    	return out * flag;
    }
    
    int N,M,A[maxn];
    
    struct node{
    	int v;
    	node *ls,*rs;
    	node() {ls = rs = NULL;}
    };
    node* rt[maxn];
    int rti = 0,pos;
    
    void Build(node **u,int l,int r){
    	*u = new node;
    	if (l == r){
    		(*u)->v = A[l];
    	}else {
    		int mid = l + r >> 1;
    		Build(&(*u)->ls,l,mid);
    		Build(&(*u)->rs,mid + 1,r);
    	}
    }
    
    void change(node *pre,node **u,int l,int r,int v){
    	(*u) = new node;
    	*(*u) = *pre;
    	if (l == r){
    		(*u)->v = v;
    	}else {
    		int mid = l + r >> 1;
    		if (mid >= pos) change(pre->ls,&(*u)->ls,l,mid,v);
    		else change(pre->rs,&(*u)->rs,mid + 1,r,v);
    	}
    }
    
    int Query(node *u,int l,int r){
    	if (l == r) return u->v;
    	else {
    		int mid = l + r >> 1;
    		if (mid >= pos) return Query(u->ls,l,mid);
    		else return Query(u->rs,mid + 1,r);
    	}
    }
    
    int main()
    {
    	N = read();
    	M = read();
    	REP(i,N) A[i] = read();
    	Build(&rt[0],1,N);
    	int pre,cmd,v;
    	while (M--){
    		pre = read();
    		cmd = read();
    		pos = read();
    		if (cmd & 1){
    			v = read();
    			change(rt[pre],&rt[++rti],1,N,v);
    		}else {
    			printf("%d
    ",Query(rt[++rti] = rt[pre],1,N));
    		}
    	}
    	return 0;
    }
    

  • 相关阅读:
    Vue 框架-09-初识组件的应用
    Vue 框架-08-基础实战 demo
    Vue 框架-07-循环指令 v-for,和模板的使用
    Vue 框架-06-条件语句 v-if 实现选项卡效果
    Vue 框架-05-动态绑定 css 样式
    Vue 框架-04-计算属性
    Vue 框架-03-键盘事件、健值修饰符、双向数据绑定
    MUI框架-14-使用自定义icon图标、引入阿里巴巴矢量图标
    在【此电脑】隐藏【设备和驱动器】中不需要的图标
    MUI框架-13-使用百度地图 API(图文教程)
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282846.html
Copyright © 2020-2023  润新知