• 线段树(点修改)


    线段树是一种数据结构……有了线段树,我们就可以对一个序列进行快速修改并查询某个区间内的最大值、最小值、和等……下面我来说一下线段树是如何实现的

    线段树就是一棵二叉树,我们对一棵二叉树上的点依次编号,从根节点开始,我们从1开始编号,然后对于每一层的点从左到右编号,这样我们不难发现有一个很重要的性质,就是对于任意一个非叶子节点,他的左儿子的编号一定是这个节点乘2,右儿子就是这个节点的编号乘2加1。

    我对于每一个节点中储存这个节点的所有的儿子节点的最大值、最小值、和,那么我们就一定可以在log(n)的时间内对于要修改的点进行更新,或者对于某个区间进行查询。

    线段树一开始肯定感觉有点乱,但最主要的还是看看代码,好好研究一下代码是怎么写的,然后慢慢理解……我是在学了C++半年之后才开始学线段树的……我一开始反正没懂……

    代买如下(这就是对于一个序列的点修改和区间查询的代码):

     1 #include<iostream>
     2 #define maxn 1000000
     3 #define INF 2000000000
     4 using namespace std;
     5 int a[maxn],maxv[3*maxn],minv[3*maxn],sumv[3*maxn];
     6 void build(int L,int R,int o)
     7 {
     8     if(L==R)maxv[o]=minv[o]=sumv[o]=a[L];
     9     else
    10     {
    11         int m=L+(R-L)/2,lc=o<<1,rc=lc+1;
    12         build(L,m,lc);
    13         build(m+1,R,rc);
    14         maxv[o]=max(maxv[lc],maxv[rc]);
    15         minv[o]=min(minv[lc],minv[rc]);
    16         sumv[o]=sumv[lc]+sumv[rc];
    17     }
    18     return;
    19 }
    20 int x,v;
    21 void update(int L,int R,int o)
    22 {
    23     if(L==R)maxv[o]=minv[o]=sumv[o]=v;
    24     else
    25     {
    26         int m=L+(R-L)/2,lc=o<<1,rc=lc+1;
    27         if(x<=m)update(L,m,lc);
    28         if(x>m)update(m+1,R,rc);
    29         maxv[o]=max(maxv[lc],maxv[rc]);
    30         minv[o]=min(minv[lc],minv[rc]);
    31         sumv[o]=sumv[lc]+sumv[rc];
    32     }
    33 }
    34 int ql,qr,_max,_min,_sum;
    35 void query(int L,int R,int o)
    36 {
    37     if(ql<=L&&R<=qr)
    38     {
    39         _max=max(_max,maxv[o]);
    40         _min=min(_min,minv[o]);
    41         _sum+=sumv[o];
    42     }
    43     else 
    44     {
    45         int m=L+(R-L)/2,lc=o<<1,rc=lc+1;
    46         if(ql<=m)query(L,m,lc);
    47         if(qr>m)query(m+1,R,rc);
    48     }
    49     return;
    50 }
    51 int main()
    52 {
    53     int n,Q;
    54     scanf("%d",&n);
    55     for(int i=1;i<=n;i++)
    56     {
    57         scanf("%d",&a[i]);
    58     }
    59     build(1,n,1);
    60     scanf("%d",&Q);
    61     while(Q--)
    62     {
    63         char t;
    64         scanf("%s",&t);
    65         if(t=='Q')
    66         {
    67             _sum=0;
    68             _min=-1u>>1;
    69             _max=1<<31;
    70             scanf("%d%d",&ql,&qr);
    71             query(1,n,1);
    72             printf("MaxNum: %d, MinNum: %d, Sum: %d
    ",_max,_min,_sum);
    73         }
    74         if(t=='C')
    75         {
    76             scanf("%d%d",&x,&v);
    77             update(1,n,1);
    78         }
    79     }
    80 }
  • 相关阅读:
    Java SE 第十一讲(面向对象之封装)续二
    Java SE 第二十六讲 包与导入语句剖析
    Java SE 第三十一,二,三 Java数组剖析,Java数组内存地址解析
    Java SE 第三十四,五,六讲 Array类解析及数组疑难剖析,冒泡排序,交换排序以及快速排序
    Java SE 第三十八,九,四十,四十一,四十二,三四IDE详细介绍,ArrayList源代码深入剖析,L
    java高效的获取指定的精度的double数
    C++ 字符常量
    C++ endl
    C++基本数据类型
    vs2005的treeview简单使用之无限级别菜单建立
  • 原文地址:https://www.cnblogs.com/543Studio/p/5222669.html
Copyright © 2020-2023  润新知