线段树模板
Posted 不可爱的小可爱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树模板相关的知识,希望对你有一定的参考价值。
1、求区间和
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 const int maxn=50000+5; 5 int a[maxn]; 6 struct Node 7 { 8 int l,r,sum; 9 } node[maxn<<2]; 10 11 //参数含义:节点区间,节点编号 12 void InitTree(int l,int r,int k) 13 { 14 node[k].r=r;//节点k的右子树 15 node[k].l=l; 16 node[k].sum=0;//权值 17 if(l==r)//到达叶子节点 18 { 19 node[k].sum=a[r]; 20 return; 21 } 22 int mid=(l+r)>>1; 23 InitTree(l,mid,k<<1);//递归建左子树 24 InitTree(mid+1,r,k<<1|1);//递归建右子树 25 26 node[k].sum=node[k<<1].sum+node[k<<1|1].sum; 27 //父节点的值为两子节点值的和 28 //此为线段树的核心所在,求最值修改这一句即可 29 } 30 void UpdateTree(int l,int r,int k,int sum) 31 { 32 if(node[k].l==l&&node[k].r==r) 33 { 34 node[k].sum+=sum; 35 return; 36 } 37 int mid=(node[k].l+node[k].r)>>1; 38 if(l>mid) 39 UpdateTree(l,r,k<<1|1,sum);//更新下一层的右子树 40 else 41 UpdateTree(l,r,k<<1,sum); 42 43 node[k].sum=node[k<<1].sum+node[k<<1|1].sum; 44 //注意:每次更新后也要更新父节点的值 45 } 46 //查询l到r的k 47 int SearchTree(int l,int r,int k) 48 { 49 if(node[k].l==l&&node[k].r==r) 50 { 51 return node[k].sum; 52 } 53 int mid=(node[k].l+node[k].r)>>1; 54 if(l>mid) 55 { 56 return SearchTree(l,r,k<<1|1);//查询右子树 57 } 58 else if(r<=mid) 59 { 60 return SearchTree(l,r,k<<1); 61 } 62 else 63 { 64 //查询区间横跨左右子树,两棵子树一起查询 65 return SearchTree(mid+1,r,k<<1|1)+SearchTree(l,mid,k<<1); 66 } 67 } 68 int main() 69 { 70 int T,kase=0; 71 cin>>T; 72 while(T--) 73 { 74 printf("Case %d:\n",++kase); 75 int n,x,y; 76 scanf("%d",&n); 77 for(int i=1;i<=n;i++) 78 { 79 scanf("%d",&a[i]); 80 } 81 InitTree(1,n,1); 82 char ch[10]; 83 while(scanf("%s",ch)) 84 { 85 if(ch[0]==‘E‘) 86 break; 87 scanf("%d%d",&x,&y); 88 if(ch[0]==‘A‘) 89 UpdateTree(x,x,1,y); 90 else if(ch[0]==‘S‘) 91 UpdateTree(x,x,1,-y); 92 else if(ch[0]==‘Q‘) 93 cout<<SearchTree(x,y,1)<<endl; 94 } 95 } 96 return 0; 97 }
2、求区间最大值
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 const int maxn=200000+5; 5 int a[maxn]; 6 struct Node 7 { 8 int l,r,sum; 9 } node[maxn<<2]; 10 11 //参数含义:节点区间,节点编号 12 void InitTree(int l,int r,int k) 13 { 14 node[k].r=r;//节点k的右子树 15 node[k].l=l; 16 node[k].sum=0;//权值 17 if(l==r)//到达叶子节点 18 { 19 node[k].sum=a[r]; 20 return; 21 } 22 int mid=(l+r)>>1; 23 InitTree(l,mid,k<<1);//递归建左子树 24 InitTree(mid+1,r,k<<1|1);//递归建右子树 25 26 node[k].sum=max(node[k<<1].sum,node[k<<1|1].sum); 27 //父节点的值为两子节点值的和 28 ///此为线段树的核心所在,求最值修改这一句即可 29 } 30 void UpdateTree(int l,int r,int k,int sum) 31 { 32 if(node[k].l==l&&node[k].r==r) 33 { 34 node[k].sum=sum; 35 return; 36 } 37 int mid=(node[k].l+node[k].r)>>1; 38 if(l>mid) 39 UpdateTree(l,r,k<<1|1,sum);//更新下一层的右子树 40 else 41 UpdateTree(l,r,k<<1,sum); 42 43 node[k].sum=max(node[k<<1].sum,node[k<<1|1].sum); 44 //注意:每次更新后也要更新父节点的值 45 } 46 //查询l到r的k 47 int SearchTree(int l,int r,int k) 48 { 49 if(node[k].l==l&&node[k].r==r) 50 { 51 return node[k].sum; 52 } 53 int mid=(node[k].l+node[k].r)>>1; 54 if(l>mid) 55 { 56 return SearchTree(l,r,k<<1|1);//查询右子树 57 } 58 else if(r<=mid) 59 { 60 return SearchTree(l,r,k<<1); 61 } 62 else 63 { 64 //查询区间横跨左右子树,两棵子树一起查询 65 return max(SearchTree(mid+1,r,k<<1|1),SearchTree(l,mid,k<<1)); 66 } 67 } 68 int main() 69 { 70 int n,m; 71 while(scanf("%d%d",&n,&m)!=EOF) 72 { 73 int x,y; 74 for(int i=1;i<=n;i++) 75 { 76 scanf("%d",&a[i]); 77 } 78 InitTree(1,n,1); 79 char ch; 80 while(m--) 81 { 82 getchar(); 83 scanf("%c",&ch); 84 scanf("%d%d",&x,&y); 85 if(ch==‘U‘) 86 UpdateTree(x,x,1,y); 87 else if(ch==‘Q‘) 88 printf("%d\n",SearchTree(x,y,1)); 89 } 90 } 91 return 0; 92 }
以上是关于线段树模板的主要内容,如果未能解决你的问题,请参考以下文章