线段树--数据结构专题学习

这两周是数据结构专题的学习,,被专题的题目虐得死去活来==

 

线段树:简单的说就是把【1,n】的区间二分,【1,(1+n)/2】左子树,【(1+n)/2+1,n】右子树

    就这样一直分下去,直到都是【x,x】这样的区间。这样就构成了一颗树了^-^

          有这样一棵树,我们就可以在节点中储存区间的和啊,区间内的最大值啊,最小值等等。。这就是线段树的附加信息了,也是题目中的重点。。

    我们可以用一个数组(长度为k)储存原区间的初始值,然后根据这个建树,所以这个树的节点数最多为4*K;

    对于每个节点i,其左子树为i*2,右子树为i*2+1,父母节点为i/2。该区间的sum为左右子树区间和的和,最大最小值同理。。。

    线段树的建立,修改,查询都是用递归写的。

    所以在对单个数值时,必定会影响到其祖先节点,所以从上往下写。递归后修改节点信息。

    线段树的查询也是如此,从上向下查询。

    先贴模板

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define MP make_pair
 6 #define PB push_back
 7 typedef long long LL;
 8 typedef pair<int,int> PII;
 9 const double eps=1e-8;
10 const double pi=acos(-1.0);
11 const int K=1e6+7;
12 const int mod=1e9+7;
13 
14 
15 struct node
16 {
17     int max,sum;
18     int left,right;
19 };
20 struct node tree[4*K];
21 int a[K];
22 void build(int id,int l,int r)
23 {
24     tree[id].left=l,tree[id].right=r;
25     if(l==r)
26         tree[id].max=tree[id].sum=a[l];
27     else
28     {
29         build(2*id,l,(l+r)/2),build(2*id+1,(l+r)/2+1,r);
30         tree[id].max=max(tree[2*id].max,tree[2*id+1].max);
31         tree[id].sum=tree[2*id].sum+tree[2*id+1].sum;
32     }
33 }
34 int queryMax(int id,int l,int r)
35 {
36     if(l==tree[id].left && r==tree[id].right)
37         return tree[id].max;
38     int mid=(tree[id].left+tree[id].right)>>1;
39     if(r<=mid)
40         return queryMax(id<<1,l,r);
41     else if(l>=mid+1)
42         return queryMax((id<<1)+1,l,r);
43     else
44         return max(queryMax(id<<1,l,mid),queryMax((id<<1)+1,mid+1,r));
45 }
46 int querySum(int id,int l,int r)
47 {
48     if (tree[id].left==l&&tree[id].right==r)
49         return tree[id].sum;
50     int mid=(tree[id].left+tree[id].right)>>1;
51     if (r<=mid)
52         return querySum(id*2,l,r);
53     else if (l>mid)
54         return querySum(id*2+1,l,r);
55     else
56         return querySum(id*2,l,mid)+querySum(id*2+1,mid+1,r);
57 }
58 void update(int id,int pos,int v)
59 {
60     if(tree[id].left == tree[id].right)
61         tree[id].sum=tree[id].max=v;
62     else
63     {
64         int mid=(tree[id].left+tree[id].right)>>1;
65         if (pos<=mid) update(id*2,pos,v);
66         else update(id*2+1,pos,v);
67         tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
68         tree[id].max=max(tree[id*2].max,tree[id*2+1].max);
69     }
70 }
71 int main(void)
72 {
73 
74     return 0;
75 }

 

    带区间修改的版本:

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdio>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <queue>
  7 #include <stack>
  8 #include <map>
  9 #include <vector>
 10 #include <cstdlib>
 11 #include <string>
 12 
 13 #define PI acos((double)-1)
 14 #define E exp(double(1))
 15 using namespace std;
 16 #define K 10000
 17 struct node
 18 {
 19     int maxt,sum,lazy;//sum代表节点信息,按题目更改
 20     int left,right;
 21 };
 22 struct node tree[4*K];
 23 int a[K];
 24 void build(int id,int l,int r)
 25 {
 26     tree[id].left=l;tree[id].right=r;tree[id].lazy=0;
 27     if(l==r)
 28     {
 29         tree[id].maxt=tree[id].sum=a[l];
 30     }
 31     else
 32     {
 33         build(2*id,l,(l+r)/2);
 34         build(2*id+1,(l+r)/2+1,r);
 35         tree[id].maxt=max(tree[2*id].maxt,tree[2*id+1].maxt);
 36         tree[id].sum=tree[2*id].sum+tree[2*id+1].sum;
 37     }
 38 }
 39 void pushdowm(int id)
 40 {
 41     if(tree[id].lazy)
 42     {
 43         tree[id*2].lazy=tree[id].lazy;
 44         tree[id*2+1].lazy=tree[id].lazy;
 45         tree[id*2].sum+=tree[id].lazy;
 46         tree[id*2+1].sum+=tree[id].lazy;
 47         tree[id].lazy=0;
 48     }
 49 }
 50 int queryMax(int id,int l,int r)
 51 {
 52     if(l==tree[id].left && r==tree[id].right)
 53         return tree[id].maxt;
 54     int mid=(tree[id].left+tree[id].right)>>1;
 55     int ret=0;
 56     pushdowm(id);
 57     if(r<=mid)
 58         ret=max(ret,queryMax(id<<1,l,r));
 59     else if(l>=mid+1)
 60         ret=max(ret,queryMax((id<<1)+1,l,r));
 61     else
 62     {
 63         int a,b;
 64         a=queryMax(id<<1,l,mid);
 65         b=queryMax((id<<1)+1,mid+1,r);
 66         return max(a,b);
 67     }
 68     return ret;
 69 }
 70 int update(int id,int pos,int v)
 71 {
 72     if(tree[id].left == tree[id].right)
 73     {
 74         tree[id].sum=tree[id].maxt=v;
 75     }
 76     else
 77     {
 78         int mid=(tree[id].left+tree[id].right)>>1;
 79         if (pos<=mid) update(id*2,pos,v);
 80             else update(id*2+1,pos,v);
 81         tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
 82         tree[id].maxt=max(tree[id*2].maxt,tree[id*2+1].maxt);
 83     }
 84     return 0;
 85 }
 86 void update_interal(int id,int l,int r,int v)
 87 {
 88     if(l==tree[id].left && r==tree[id].right)
 89     {
 90         tree[id].lazy+=v,tree[id].sum+=v;return;
 91     }
 92     pushdowm(id);
 93     int mid=(tree[id].left+tree[id].right)>>1;
 94     if(r<=mid)
 95         update_interal(id*2,l,r,v);
 96     else if(l>mid)
 97         update_interal(id*2+1,l,r,v);
 98     else
 99     {
100         update_interal(id*2,l,mid,v);
101         update_interal(id*2+1,mid+1,r,v);
102         tree[id].sum+=tree[id*2].sum+tree[id*2+1].sum;
103     }
104 }
105 int query(int id,int l,int r)
106 {
107         if (tree[id].left==l&&tree[id].right==r)
108             return tree[id].sum;
109         else
110         {
111             int mid=(tree[id].left+tree[id].right)>>1;
112             pushdowm(id);
113             if (r<=mid) return query(id*2,l,r);
114             else if (l>mid) return query(id*2+1,l,r);
115             else return query(id*2,l,mid)+query(id*2+1,mid+1,r);
116         }
117 }
118 
119 int main(void)
120 {
121     int n,l,r,v;
122     cin>>n;
123     for(int i=1;i<=n;i++)
124         a[i]=i;
125     build(1,1,n);
126     printf("%d\n",query(1,1,10));
127     cin>>l>>r>>v;
128     update_interal(1,l,r,v);
129     printf("%d\n",query(1,l,r));
130     return 0;
131 }
View Code

 

posted @ 2016-04-23 00:18  weeping  阅读(203)  评论(0编辑  收藏  举报