線段樹模板
阿新 • • 發佈:2017-09-28
print dac gif date aps 所在 ret 線段樹模板 核心
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 }求最大值
線段樹模板