【原创】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组账单的值直接建到树里

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

原文地址:https://www.cnblogs.com/liwenchi/p/5760660.html