1. 程式人生 > >線段樹模板

線段樹模板

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 }
求最大值

線段樹模板