首页 > 其他分享 >主席树初步

主席树初步

时间:2023-10-24 17:12:25浏览次数:40  
标签:结点 ch LL tot 初步 修改 线段 主席

什么是主席树
  • 主席树即可持久化线段树

  • 这边其实我目前感觉就是支持查询历史版本的线段树

原理
  • 每当线段树修改时,维护其过去的版本,将其复制下来(然后就MLE了

  • 改进:对集合的每一个版本维护一个单独的根,在修改数据时,只复制树的一部分

  • (复制一张别人的图Orz)

别人的图

建树
  • 类似普通线段树,新建节点
单点更新
  • 引用一下别人的博客

我们要修改一个叶子结点的值,并且不能影响旧版本的结构。
在从根结点递归向下寻找目标结点时,将路径上经过的结点都复制一份。
找到目标结点后,我们新建一个新的叶子结点,使它的值为修改后的版本,并将它的地址返回。
对于一个非叶子结点,它至多只有一个子结点会被修改,那么我们对将要被修改的子结点调用修改函数,那么就得到了它修改后的儿子。
在每一步都向上返回当前结点的地址,使父结点能够接收到修改后的子结点。
在这个过程中,只有对新建的结点的操作,没有对旧版本的数据进行修改。

  • 其实我这里觉得和建树一样和普通线段树差不太多,只要在原本基础上新建节点就行
区间查询:
  • 感觉和普通的区别不大,要查询的版本的根节点开始查就行
代码实现
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL a[0x66ccff*5],n,q,rt[0x66ccff*5];
inline LL read(){
    LL f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
LL lc[0x66ccff*5],rc[0x66ccff*5],val[0x66ccff*5],ans,m,v;
inline void build(LL &q,LL l,LL r){
    q=++ans;
    if(l==r){
        val[q]=a[l];
        return;
    }
    LL mid=(l+r)>>1;
    build(lc[q],l,mid);
    build(rc[q],mid+1,r);
}
inline void change(LL &m,LL tot,LL l,LL r,LL q,LL v){
    m=++ans;//新建节点
    lc[m]=lc[tot];
    rc[m]=rc[tot];
    val[m]=val[tot];
    if(l==r){
        val[m]=v;
        return;
    }
    LL mid=(l+r)>>1;
    if(q<=mid)
        change(lc[m],lc[tot],l,mid,q,v);
    else 
        change(rc[m],rc[tot],mid+1,r,q,v);
}
inline LL ask(LL m,LL l,LL r,LL q){
    if(l==r)
        return val[m];
    else{
        LL mid=(l+r)>>1;
        if(q<=mid)
            return ask(lc[m],l,mid,q);
        else 
            return ask(rc[m],mid+1,r,q);
    }
}
int main(){
    n=read(),m=read();
    for(LL i=1;i<=n;i++)
        a[i]=read();
    build(rt[0],1,n);
    for(LL i=1;i<=m;i++){
        LL tot=read(),opt=read(),x=read();
        if(opt==1)
			v=read();
			change(rt[i],rt[tot],1,n,x,v);
        if(opt==2){
			cout<<ask(rt[tot],1,n,x)<<"\n";
			rt[i]=rt[tot];
		}
    }
}

咕咕咕好像没学明白

标签:结点,ch,LL,tot,初步,修改,线段,主席
From: https://www.cnblogs.com/LuoTianYi66ccff/p/17785262.html

相关文章

  • uboot配置usbhost及代码初步分析--Apple的学习笔记
    一,前言之前uboot没配置过usb,但是现在uboot基于DM模型基本和linuxdriver类似了。那么为了学习linuxdriver,我可以先学习uboot来做技术储备也是一样的。而且usb在uboot上应该也有用武之地,所以有必要进行刻意练习。二,分析1,之前对发现driver用了wraper的方式来打包进行绑定,我理解唯一......
  • 2. STM32 HAL库结构的初步分析
    1.以串口为例,添加串口的HAL库源码我们使用的是异步通信的方式,因此将stm32f1xx_hal_uart.c添加进来。在本次学习中,串口我们使用3种方式去学习,轮询、中断、DMA方式。因此,我们也将DMA的HAL库源码添加进来。 ......
  • 【模板】二维计算几何初步
    template<classT>structpoint{Tx,y;point():point(0,0){}point(Tx,Ty):x(x),y(y){}friendpointoperator+(constpoint&lhs,constpoint&rhs){return{lhs.x+rhs.x,lhs.y+rhs.y};}friend......
  • java模块化初步理解
    1.先看两个命令:jdepsHelloWorld.classHelloWorld.class->java.base<unnamed>->java.iojava.base<unnamed>-......
  • Acwing 800.数组元素的目标和,双指针初步
    Acwing800.数组元素的目标和给定升序的有序数组A(长度为n),B(长度为m)以及目标值x,求出满足\(A[i]+B[j]=x\)的数对\((i,j)\),题目保证仅有唯一解输入样例:456124734689输出样例:11双指针来做定义指针i,j,其中i指向A,j指向B,且i=0,指向A的首元素,j=m-1,指向B的末......
  • 自动配置原理的初步总结
    启动类里面的@SpringBootApplication注解封装了三个注解 1.@SpringBootConfiguration声明配置类 2.@ComponentScan组件扫描,默认本包和其子包 3.@EnableAutoConfiguration封装了@import注解,可以直接导入 @Bean,将当前方法交给容器管理,成为IOC容器的Bean(针对第三方......
  • 生成函数初步
    普通生成函数(OGF)形式\[F=\sum_{n\geq0}\f_n\x^n\]基本运算1.相加\[F\pmG=\sum_{n\geq0}\(f_n\pmg_n)\x^n\]2.卷积\[F\cdotG=\sum_{n\geq0}\x^n\\sum_{i=0}^nf_ig_{n-i}\]几种常见的幂级数求和\[f={0,1,1,1,......
  • Vue源码学习(十一):计算属性computed初步学习
    好家伙,  1.Computed实现原理if(opts.computed){initComputed(vm,opts.computed);}functioninitComputed(vm,computed){//存放计算属性的watcherconstwatchers=vm._computedWatchers={};for(constkeyincomputed){constuser......
  • 集合论初步
    零、弁言或者更像是一种读书笔记。鉴于笔者的低下智力,以这种方式来把第一次阅读时的一些可能的问题或思考过程进行记录。其余的一些文本会在闲暇时更新。前提是我还活着。这里是康托的乐园。欢迎各位。1.一些无聊的数学史——有关于无穷Aristotle首次提出潜在的无穷概念,并......
  • 主席树
    权值线段树思路:现将数值离散化每个节点存的是值在\(l\)~\(r\)之间的数的个数,用线段树维护作用:求\(k\)小值或\(k\)大值查某一数值的排名查询数组排序查前驱、后继求逆序对相比平衡树:码量小、简单P1801黑匣子离散化:sort(alls.begin(),alls.end());alls.eras......