• 【原创】tyvj1038 忠诚 & 计蒜客 管家的忠诚 & 线段树(单点更新,区间查询)


    最简单的线段树之一,中文题目,不翻译。。。。

    注释讲的比较少,这已经是最简单的线段树,如果看不懂真的说明最基础的理论没明白

    推荐一篇文章http://www.cnblogs.com/liwenchi/p/5760498.html

    可能和我的线段树风格不一样,无所谓啦,多理解,理解了就可以自己编自己喜欢风格的模板

    前排强势提醒!!!线段树的函数中只要涉及到区间(更新/查询),就有一个很容易出错的点。

    详情见我的另一篇:http://www.cnblogs.com/liwenchi/p/5761257.html

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 #define N 1000003
     6 int ans[1000003];
     7 struct nod
     8 {
     9     int l,r;
    10     int data;
    11 }tree[5*N];
    12 
    13 void push_up(int i)
    14 {
    15     tree[i].data = min(tree[i*2].data,tree[i*2+1].data);//更新tree[i]的最小值,由左孩子右孩子节点决定
    16 }
    17 void build_tree(int i,int l,int r)
    18 {
    19     tree[i].l=l;
    20     tree[i].r=r;
    21     tree[i].data = 0;
    22     if(l==r)
    23     {
    24         return ;
    25     }
    26     int mid=(l+r)/2;
    27     build_tree(i*2,l,mid);
    28     build_tree(i*2+1,mid+1,r);
    29     push_up(i); //理论上讲,建树不用加这个,加了也不错
    30 }
    31 void updata(int i,int k,int v)//更新
    32 {
    33     if(tree[i].l==k&&tree[i].r==k)
    34     {
    35         tree[i].data=v;
    36         return ;
    37     }
    38     int mid=(tree[i].l+tree[i].r)/2;
    39     if(k<=mid)      //这里要是不懂,可以类比二叉排序树
    40         updata(i*2,k,v);
    41     else
    42         updata(i*2+1,k,v);
    43     push_up(i); //更新应该要加的啊哦,更新完以后,更新这个点的最小值
    44 }
    45 
    46 int query(int i,int l,int r)//查询
    47 {
    48     if(l<=tree[i].l&&tree[i].r<=r)
    49     {
    50         return tree[i].data;
    51     }
    52     int mid=(tree[i].l+tree[i].r)/2;
    53     if(r<=mid)   //如果R都小于MID了,说明一定是从左孩子节点来的(这里一开始怒错无数次,后来这样写过了,至今不知道为什么....)
    54         return query(i*2,l,r);
    55     if(l>mid)    //如果L都大于MID了,说明一定是从右孩子节点来的
    56         return query(i*2+1,l,r);
    57     return min(query(i*2,l,r),query(i*2+1,l,r));//否则是从两个孩子节点来的,比较出最小值返回
    58 }
    59 int main()
    60 {
    61     int n,m,top = 0;
    62     scanf("%d%d",&m,&n);
    63     build_tree(1,1,m);
    64     for(int i=1;i<=m;i++)
    65     {
    66         int account;
    67         scanf("%d",&account);
    68         updata(1,i,account);
    69     }
    70     for(int i=1;i<=n;i++)
    71     {
    72         int l,r;
    73         scanf("%d%d",&l,&r);
    74         ans[top++] = query(1,l,r);
    75     }
    76     for(int i=0;i<top-1;i++)
    77         printf("%d ",ans[i]);
    78     printf("%d",ans[top - 1]);//输出有点坑
    79 }

    当然也可以不要更新节点的函数,建树的时候直接把n组账单的值直接建到树里

    我这种写法只是更具有一般性啦

  • 相关阅读:
    Github进不去解决方法
    微信小程序中使用iconfont的方法
    curl实现SFTP上传下载文件
    curl实现SFTP上传下载文件
    curl不支持sftp的解决方法
    sscanf遇到回车换行认为字符串结束,怎样让它忽略这些回车换行继续搜索整个字符串?
    史上最全阿里 Java 面试题总结及答案
    VS Code的Error: Running the contributed command: ‘_workbench.downloadResource‘ failed解决
    云锵投资 2021 年 07 月简报
    看完段永平的100条思考,我终于悟出他为何这么牛…(转载)
  • 原文地址:https://www.cnblogs.com/liwenchi/p/5760660.html
Copyright © 2020-2023  润新知