线段树(二)

第一篇以一道简单的题目为背景介绍了线段树的基本结构和基本性质,这一篇我们使用线段树来解决几个常见的问题

1. 查询区间最大(小)值

支持两种操作:a. 修改某个点的值

                       b. 查询某个区间的最大(小)值

 1 #include <stdio.h>
 2 #define N 1024
 3 
 4 typedef struct {
 5     int min_value;
 6     int left;
 7     int right;
 8 } ST;
 9 
10 int  input[N + 1];
11 int father[N + 1];
12 ST  st[N * 2 + 1];
13 
14 
15 /* 查询 */
16 int query_ST(int i, int left, int right) {
17     if(left == right) {
18         return st[father[left]].min_value;
19     }
20     int l = st[i].left;
21     int r = st[i].right;
22     if(l == left && r == right) {
23         return st[i].min_value;
24     }
25     else if(right <= (r + l) / 2) {
26         return query_ST(i * 2, left, right);
27     }
28     else if(left > (r + l) / 2) {
29         return query_ST(i * 2 + 1, left, right);
30     }
31     else {
32         int min_l = query_ST(i * 2, left, (l + r) / 2);
33         int min_r = query_ST(i * 2 + 1, (l + r) / 2 + 1, right);
34         return  min_l = min_l < min_r ? min_l : min_r;
35     }
36 }
37 
38 /* 修改 */
39 void modify_ST(int pos, int value) {
40     int i = father[pos];
41     int min_l, min_r;
42     st[i].min_value = value;
43     i = i / 2;
44     while(i) {
45         min_l = st[i * 2].min_value;
46         min_r = st[i * 2 + 1].min_value;
47         min_l = min_l < min_r ? min_l : min_r;
48         if(st[i].min_value == min_l) break;
49         st[i].min_value = min_l;
50         i = i / 2;
51     }
52 }
53 
54 /* 建树 */
55 int build_ST(int i, int left, int right) {
56     st[i].left = left;
57     st[i].right = right;
58     if(left == right) {
59         father[left] = i;
60         st[i].min_value = input[left];
61         return input[left];
62     }
63     int min_l = build_ST(i * 2, left, (left + right) / 2);
64     int min_r = build_ST(i * 2 + 1, (left + right) / 2 + 1, right);
65     min_l = min_l < min_r ? min_l : min_r;
66     return st[i].min_value = min_l;
67 }
68 
69 int main() {
70     int m, n;
71     int b_mod, left, right;
72     scanf("%d", &n);
73     for(int i = 0; i < n; i++) {
74         scanf("%d", &input[i]);
75     }
76     scanf("%d", &m);
77     build_ST(1, 0, n - 1);
78     for(int i = 0; i < m; i++) {
79         scanf("%d %d %d", &b_mod, &left, &right);
80         if(b_mod) { modify_ST(left - 1, right); }
81         else { printf("%d
", query_ST(1, left - 1, right - 1)); }
82     }
83     return 0;
84 }

2.  查询区间和(乘积)值

支持两种操作:a. 修改某个区间的值

                       b. 查询某个区间的和

这里使用了lazy的思想,即查询时更新

  1 #include <stdio.h>
  2 #define N 1024 * 1024
  3 
  4 typedef struct {
  5     int left;
  6     int righ;
  7     int lazy;
  8     int sum;
  9 }st_node;
 10 
 11 st_node st[N + 1];
 12 int  seg[2 * N + 1];
 13 
 14 int build_st(int i, int left, int righ) {
 15     st[i].left = left;
 16     st[i].righ = righ;
 17     if(left == righ) {
 18         st[i].sum = seg[left];
 19         st[i].lazy = -1;
 20         return st[i].sum;
 21     }
 22     int l_sum = build_st(i * 2, left, (left + righ) / 2);
 23     int r_sum = build_st(i * 2 + 1, (left + righ) / 2 + 1, righ);
 24     st[i].sum = l_sum + r_sum;
 25     st[i].lazy = -1;
 26     return l_sum + r_sum;
 27 }
 28 int modify_st(int i, int left, int righ, int value) {
 29     if(st[i].left == left && st[i].righ == righ) {
 30         st[i].lazy = value;
 31         st[i].sum = (righ + 1 - left) * value;
 32         return st[i].sum;
 33     }
 34     else {
 35         if(-1 != st[i].lazy) {
 36             int l_len = st[i * 2].righ + 1 - st[i * 2].left; 
 37             st[i * 2].lazy = st[i].lazy;
 38             st[i * 2].sum = l_len * st[i * 2].lazy;
 39 
 40             int r_len = st[i * 2 + 1].righ + 1 - st[i * 2 + 1].left;
 41             st[i * 2 + 1].lazy = st[i].lazy;
 42             st[i * 2 + 1].sum = r_len * st[i * 2 + 1].lazy;
 43 
 44             st[i].lazy = -1;            
 45         }
 46         int l = st[i].left;
 47         int r = st[i].righ;
 48         int l_sum = st[i * 2].sum;
 49         int r_sum = st[i * 2 + 1].sum;
 50         if(righ <= (r + l) / 2) {
 51             l_sum = modify_st(i * 2, left, righ, value);
 52         }
 53         else if(left > (r + l) / 2) {
 54             r_sum = modify_st(i * 2 + 1, left, righ, value);
 55         }
 56         else {
 57             l_sum = modify_st(i * 2, left, (l + r) / 2, value);
 58             r_sum = modify_st(i * 2 + 1, (l + r) / 2 + 1, righ, value);
 59         }
 60         st[i].sum= l_sum + r_sum;
 61         return st[i].sum;
 62     }
 63 }
 64 
 65 int query_st(int i, int left, int righ) {
 66     if(st[i].left == left && st[i].righ == righ) {
 67         return st[i].sum;
 68     }
 69     else {
 70         if(-1 != st[i].lazy) {
 71             int l_len = st[i * 2].righ - st[i * 2].left + 1;     
 72             st[i * 2].lazy = st[i].lazy;
 73             st[i * 2].sum = l_len * st[i * 2].lazy;
 74 
 75             int r_len = st[i * 2 + 1].righ + 1 - st[i * 2 + 1].left;
 76             st[i * 2 + 1].lazy = st[i].lazy;
 77             st[i * 2 + 1].sum = r_len * st[i * 2 + 1].lazy;
 78 
 79             st[i].lazy = -1;
 80         }
 81         int l = st[i].left;
 82         int r = st[i].righ;
 83         int l_sum = 0;
 84         int r_sum = 0;
 85         if(righ <= (r + l) / 2) {
 86             l_sum = query_st(i * 2, left, righ);
 87         }   
 88         else if(left > (r + l) / 2) {
 89             r_sum = query_st(i * 2 + 1, left, righ);
 90         } 
 91         else {
 92             l_sum = query_st(i * 2, left, (l + r) / 2);
 93             r_sum = query_st(i * 2 + 1, (l + r) / 2 + 1, righ);                                                    
 94         }
 95         return l_sum + r_sum;
 96     }
 97 }
 98 
 99 int main() {
100     int i, n, m;
101     scanf("%d", &n);
102     for(i = 1; i <= n; i++) {
103         scanf("%d", &seg[i]);
104     }
105     build_st(1, 1, n);
106     scanf("%d", &m);
107     for(i = 0; i < m; i++) {
108         int mode;
109         int left;
110         int righ;
111         int value;
112         scanf("%d", &mode);
113         if(mode) { 
114             scanf("%d %d %d", &left, &righ, &value); 
115             modify_st(1, left, righ, value);
116         }
117         else {
118             scanf("%d %d", &left, &righ);
119             printf("%d
", query_st(1, left, righ));
120         }
121     }
122     return 0;
123 }

3. 线段投影长度

原文地址:https://www.cnblogs.com/zhuoyuan/p/4139753.html