HDU1754 && HDU1166 线段树模板题

HDU1754

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754

题目分析:对于给出的一个很长的区间,对其进行单点更新值和区间求最大值的操作,由于查询的区间很大,且查询次数多,这里用线段树求解将是十分合适的

注意点:1.对于存放线段树的数组大小需要开大一些

    2.对于c语言的字符输入%c之前需要加一个空格保证输入准确

 1 #include<iostream>
 2 #include<string.h>
 3 using namespace std;
 4 
 5 const int N = 200005;
 6 int grade[N];
 7 int tree[N<<2];                    //这里建立的树的数组大小需要是N的4倍 否则不够用 
 8 int n, m;
 9 
10 int max(int a, int b){
11     if(a > b) return a;
12     else return b;
13 }
14 
15 void build_tree(int start, int end, int node){                    //线段树的建立 
16     if(start == end){
17         tree[node] = grade[start];
18     }else{
19         int mid = (start + end) / 2;
20         int left_node = node*2;
21         int right_node = node*2+1;
22         
23         build_tree(start, mid, left_node);
24         build_tree(mid+1, end, right_node);
25         tree[node] = max(tree[left_node], tree[right_node]);
26     }
27 }
28 
29 void update_tree(int start, int end, int node, int index, int value){    //单点更新值 
30     if(start == end){
31         tree[node] = value;
32     }else{
33         int mid = (start + end) / 2;
34         int left_node = node*2;
35         int right_node = node*2+1;
36         
37         if(index <= mid)
38             update_tree(start, mid, left_node, index, value);
39         else
40             update_tree(mid+1, end, right_node, index, value);
41         tree[node] = max(tree[left_node], tree[right_node]);
42     }
43 }
44 
45 int search_tree(int start, int end, int node, int l, int r){        //区间查询最大值 
46     if(l > end || r < start){
47         return 0;
48     }else if(l <= start && r >= end){
49         return tree[node];
50     }else if(start == end){      //这里的个递归出口放在后面是有原因的,有可能存在start==end 但是l和r根本和start end没有交集的情况,所以先判去了后者
51         return tree[node];
52     }
53     int mid = (start + end) / 2;
54     int left_node = node*2;
55     int right_node = node*2+1;
56     
57     int left_max = search_tree(start, mid, left_node, l, r);
58     int right_max = search_tree(mid+1, end, right_node, l, r);
59     int ans = max(left_max, right_max);
60     return ans;
61 }
62 
63 int main(){
64     while(scanf("%d%d", &n, &m) != EOF){
65         for(int i = 1; i <= n; i++)
66             scanf("%d", &grade[i]);
67         build_tree(1, n, 1);    
68         for(int i = 1; i <= m; i++){
69             char c;
70             int a, b;
71             scanf(" %c %d %d", &c, &a, &b);            //对于c语言的输入字符在%c之前需要一个空格,否则c就读取不到需要的字符了 
72             if(c == 'U') update_tree(1, n, 1, a, b);
73             else{
74                 int ans = search_tree(1, n, 1, a, b);
75                 printf("%d
", ans);
76             }
77         }
78     }    
79     return 0;
80 }

HDU1166

题目分析:

也是一题线段树的模板题,单点更新和区间查询求和(本质上和区间求最大值是一样的)

代码:

 1 #include<iostream>
 2 #include<string>
 3 #include<string.h>
 4 using namespace std;
 5 
 6 const int N = 500005;
 7 int peo[N];
 8 int tree[N<<2];
 9 
10 void build_tree(int start, int end, int node){
11     if(start == end){
12         tree[node] = peo[start];
13     }else{
14         int mid = (start + end) / 2;
15         int left_node = node*2;
16         int right_node = node*2+1;
17         
18         build_tree(start, mid, left_node);
19         build_tree(mid+1, end, right_node);
20         tree[node] = tree[left_node] + tree[right_node];
21     }
22 }
23 
24 void update_tree(int start, int end, int node, int index, int value){
25     if(start == end){
26         tree[node] += value;
27     }else{
28         int mid = (start + end) / 2;
29         int left_node = node*2;
30         int right_node = node*2+1;
31         
32         if(index <= mid)
33             update_tree(start, mid, left_node, index, value);
34         else
35             update_tree(mid+1, end, right_node, index, value);
36         tree[node] = tree[left_node] + tree[right_node];    
37     }
38 }
39 
40 int query_tree(int start, int end, int node, int l, int r){
41     if(end < l || start > r){
42         return 0;
43     }else if(start >= l && end <= r){
44         return tree[node];
45     }else if(start == end){
46         return tree[node];
47     }
48     int mid = (start + end)    / 2;
49     int left_node = node*2;
50     int right_node = node*2+1;
51     
52     int left_sum = query_tree(start, mid, left_node, l, r);
53     int right_sum = query_tree(mid+1, end, right_node, l, r);
54     int ans = left_sum + right_sum;
55     return ans;
56 }
57 
58 int main(){
59     int t;
60     scanf("%d", &t);
61     int cnt = 1;
62     while(t--){
63         printf("Case %d:
", cnt++);
64         int n;
65         scanf("%d", &n);
66         for(int i = 1; i <= n; i++)
67             scanf("%d", &peo[i]);
68         build_tree(1, n, 1);
69         string s;
70         int a, b;
71         while(cin>>s){
72             if(s == "End") break;
73             scanf("%d%d", &a, &b);
74             if(s == "Query"){
75                 int ans = query_tree(1, n, 1, a, b);    
76                 printf("%d
", ans);
77             }
78             if(s == "Add"){
79                 update_tree(1, n, 1, a, b);
80             }
81             if(s == "Sub"){
82                 update_tree(1, n, 1, a, -b);
83             }
84         }
85     }
86     return 0;
87 } 
原文地址:https://www.cnblogs.com/findview/p/11811802.html