这两周是数据结构专题的学习,,被专题的题目虐得死去活来==
线段树:简单的说就是把【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 ",query(1,1,10)); 127 cin>>l>>r>>v; 128 update_interal(1,l,r,v); 129 printf("%d ",query(1,l,r)); 130 return 0; 131 }