zoukankan      html  css  js  c++  java
  • 可持久化数据结构学习笔记

    学习了一段时间的可持久化数据结构,感觉自己的脑子不太够用。。。。

    好吧,先从最基本的看起

    可持久化数组

    题目链接

    你需要维护这样的一个长度为 N 的数组,支持如下几种操作

    1.在某个历史版本上修改某一个位置上的值

    2.访问某个历史版本上的某一位置的值

    此外,每进行一次操作(对于操作2,即为生成一个完全一样的版本,不作任何改动),就会生成一个新的版本。版本编号即为当前操作的编号(从1开始编号,版本0表示初始状态数组)

     

    一个很暴力的想法是将所有的版本都存下来,然后每次修改是复制一遍

    这样可以O(1)查询,但是要O(N)修改,而且空间复杂度。。。。。

    可以发现每次修改只会对一个位置产生影响,那我们为什么每次都要对所有的位置进行复制呢?

    我们可以利用可持久化线段树来解决可持久化数组的问题

    维护n个单点修改单点查询的线段树

    为了利用重复的空间

    每次修改时,我们就创立一个新的节点

    然后使得新的根可以访问到该节点

    这样就实现了可持久化数组

    right,left数组储存左右儿子的编号,t数组储存线段树节点的信息

    r数组储存根节点的编号

    不同的根节点可以访问不同的版本

    注意一下,right,left,t数组一般空间都要开到20到30倍

    # include<cstring>
    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<algorithm>
    const int mn = 1000005;
    int n,m;
    int cnt;
    int left[mn*20],right[mn*20],r[mn],t[mn*20];
    int build(int l,int r)
    {
         int root=++cnt;
         if(l==r)
         {
             scanf("%d",&t[root]);
             return root;
         }
         int mid=l+r>>1;
         left[root]=build(l,mid);
         right[root]=build(mid+1,r);
         return root;
    }
    void query(int rt,int l,int r,int x)
    {
        if(l==r)
        {
            printf("%d
    ",t[rt]);
            return ;
        }
        int mid=l+r>>1;
        if(x<=mid)
           query(left[rt],l,mid,x);
        else query(right[rt],mid+1,r,x);
    }
    int update(int rt,int l,int r,int pos,int x)
    {
        int root=++cnt;
        if(l==r)
        {
            t[root]=x;
            return root;
        }
        left[root]=left[rt],right[root]=right[rt];
        int mid=l+r>>1;
        if(pos<=mid)
           left[root]=update(left[rt],l,mid,pos,x);
        else right[root]=update(right[rt],mid+1,r,pos,x);
        return root;
    }
    int main()
    {
        int x,y,opt,z;
        scanf("%d%d",&n,&m);
        build(1,n);
        r[0]=1;
        for(int i=1;i<=m;i++)
        {
           scanf("%d%d",&x,&opt);
           if(opt==1)
           {
               scanf("%d%d",&y,&z);
               r[i]=update(r[x],1,n,y,z);
           }
           else {
              scanf("%d",&y);
              r[i]=r[x];
              query(r[x],1,n,y);
           }
        }
        return 0;
    }

    博主是弱弱,不对的地方还请神犇指出

  • 相关阅读:
    解析iscroll-小demo
    iscroll的理解
    jquery代码小片段
    jQuery的性能优化
    事件代理
    数组方式使用jQuery对象
    循环时的dom操作
    JavaScript中的ajax(二)
    jQuery与ajax的应用(一)
    表单应用
  • 原文地址:https://www.cnblogs.com/logeadd/p/8890374.html
Copyright © 2011-2022 走看看