我是靠谱客的博主 娇气裙子,这篇文章主要介绍HDU 1166 - 敌兵布阵 ( 线段树 )AC代码,现在分享给大家,希望可以做个参考。

题意

给出n个敌兵阵营的人数,给出一些操作命令:
(1) Add i j , 第i个营地增加j个人
(2)Sub i j , 第i个营地减少j个人(j不超过30);
(3)Query i j , 询问第i到第j个营地的总人数;
(4)End 表示结束

思路

线段树模板题 /*单点覆盖,区间查询*/

下面记录一下几个好用的线段树模板:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*单点覆盖,区间查询*/ #include <cstdio> #include <algorithm> #include <iostream> #include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 100007; const int INF=0x7fffffff; int MAX[maxn<<2]; int MIN[maxn<<2]; int SUM[maxn<<2]; void PushUP(int rt) { MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]); MIN[rt] = min(MIN[rt<<1] , MIN[rt<<1|1]); SUM[rt] = SUM[rt<<1] + SUM[rt<<1|1]; } //所有的 l ,r ,rt 参数为 1,n, 1 其中n为区间长度 void build(int l,int r,int rt) { //建树 if (l == r) { MAX[rt] = MIN[rt] =SUM[rt]=0; //初始化线段树为0的写法 /* //边读入边建树的写法,复杂度O(n) 若执行n次更新来初始化的话复杂度为O(nlogn) scanf("%d",&MAX[rt]); MIN[rt] = MAX[rt]; SUM[rt] = MAX[rt]; */ return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUP(rt); } void update(int p,int v,int l,int r,int rt) { //单点替换,把p位置的值置为v if (l == r) { MAX[rt] = v; MIN[rt] = v; SUM[rt] = v; return ; } int m = (l + r) >> 1; if (p <= m) update(p , v ,lson); else update(p , v , rson); PushUP(rt); } void update1(int p,int addv,int l,int r,int rt) { //单点增加,把p位置的值增加v if (l == r) { SUM[rt] = SUM[rt] + addv; MIN[rt] = MIN[rt] + addv; MAX[rt] =MAX[rt]+addv; return ; } int m = (l + r) >> 1; if (p <= m) update1(p , addv ,lson); else update1(p , addv , rson); PushUP(rt); } int queryMAX(int L,int R,int l,int r,int rt) { //求L~R的最大值 if (L <= l && r <= R) { return MAX[rt]; } int m = (l + r) >> 1; int ret = -INF; if (L <= m) ret = max(ret , queryMAX(L , R , lson)); if (R > m) ret = max(ret , queryMAX(L , R , rson)); return ret; } int queryMIN(int L,int R,int l,int r,int rt) { //求L~R的最小值 if (L <= l && r <= R) { return MIN[rt]; } int m = (l + r) >> 1; int ret = INF; if (L <= m) ret = min(ret , queryMIN(L , R , lson)); if (R > m) ret = min(ret , queryMIN(L , R , rson)); return ret; } int querySUM(int L,int R,int l,int r,int rt) { //求L~R的和 if (L <= l && r <= R) { return SUM[rt]; } int m = (l + r) >> 1; int ret = 0; if (L <= m) ret += querySUM(L , R , lson); if (R > m) ret += querySUM(L , R , rson); return ret; } int main() { int n , m; while (~scanf("%d%d",&n,&m)) { build(1 , n , 1); while (m --) { char op[2]; int a , b; scanf("%s%d%d",op,&a,&b); if (op[0] == 'Q') { //区间求最大 printf("%dn",queryMAX(a , b , 1 , n , 1)); } else if(op[0]=='U') //单点替换 update(a , b , 1 , n , 1); else if(op[0]=='M') { //区间求最小 printf("%dn",queryMIN(a , b , 1 , n , 1)); } else if(op[0]=='H') { //区间求和 printf("%dn",querySUM(a , b , 1 , n , 1)); } else if(op[0]=='S') { //单点增加 update1(a , b , 1 , n , 1); } else if(op[0]=='E') { //单点减少 update1(a , -b , 1 , n , 1); } } } return 0; }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* 区间覆盖,区间查询*/ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #define max(a,b) (a>b)?a:b #define min(a,b) (a>b)?b:a #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 100100; const int INF=0x7fffffff; using namespace std; int lazy[maxn<<2]; int MAX[maxn<<2]; int MIN[maxn<<2]; int SUM[maxn<<2]; void PushUp(int rt) { //由左孩子、右孩子向上更新父节点 SUM[rt] = SUM[rt<<1] + SUM[rt<<1|1]; MAX[rt] = max(MAX[rt<<1],MAX[rt<<1|1]); MIN[rt] = min(MIN[rt<<1],MIN[rt<<1|1]); } void PushDown(int rt,int m) { //向下更新 if (lazy[rt]) { //懒惰标记 lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt]; SUM[rt<<1] = (m - (m >> 1)) * lazy[rt]; SUM[rt<<1|1] = ((m >> 1)) * lazy[rt]; MAX[rt<<1]=MAX[rt<<1|1]=lazy[rt]; MIN[rt<<1]=MIN[rt<<1|1]=lazy[rt]; lazy[rt] = 0; } } //所有的l,r,rt 带入1,n,1 void build(int l,int r,int rt) { //初始化建树 lazy[rt] = 0; if (l== r) { SUM[rt]=MAX[rt]=MIN[rt]=0; //初始化为0的建树 /*scanf("%d",&SUM[rt]); //边读入边建树的方法 MAX[rt]=MIN[rt]=SUM[rt]; */ return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUp(rt); } void update(int L,int R,int v,int l,int r,int rt) { //将L~R区间的值置为v //if(L>l||R>r) return; if (L <= l && r <= R) { lazy[rt] = v; SUM[rt] = v * (r - l + 1); MIN[rt] = v; MAX[rt] = v; //printf("%d %d %d %d %dn", rt, sum[rt], c, l, r); return ; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; if (L <= m) update(L , R , v , lson); if (R > m) update(L , R , v , rson); PushUp(rt); } int querySUM(int L,int R,int l,int r,int rt) { //求区间L~R的和 if (L <= l && r <= R) { //printf("%dn", sum[rt]); return SUM[rt]; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; int ret = 0; if (L <= m) ret += querySUM(L , R , lson); if (m < R) ret += querySUM(L , R , rson); return ret; } int queryMIN(int L,int R,int l,int r,int rt) { //求区间L~R的最小值 if (L <= l && r <= R) { //printf("%dn", sum[rt]); return MIN[rt]; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; int ret = INF; if (L <= m) ret = min(ret, queryMIN(L , R , lson)); if (m < R) ret = min(ret,queryMIN(L , R , rson)); return ret; } int queryMAX(int L,int R,int l,int r,int rt) { //求区间L~R的最大值 if (L <= l && r <= R) { //printf("%dn", sum[rt]); return MAX[rt]; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; int ret = -INF; if (L <= m) ret = max(ret, queryMAX(L , R , lson)); if (m < R) ret = max(ret,queryMAX(L , R , rson)); return ret; } int main() { int n , m; char str[5]; while(scanf("%d%d",&n,&m)) { build(1 , n , 1); while (m--) { scanf("%s",str); int a , b , c; if(str[0]=='T') { scanf("%d%d%d",&a,&b,&c); update(a , b , c , 1 , n , 1); } else if(str[0]=='Q') { scanf("%d%d",&a,&b); cout<<querySUM(a,b,1,n,1)<<endl; } else if(str[0]=='A') { scanf("%d%d",&a,&b); cout<<queryMAX(a,b,1,n,1)<<endl; } else if(str[0]=='I') { scanf("%d%d",&a,&b); cout<<queryMIN(a,b,1,n,1)<<endl; } } } return 0; }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* 区间增加,区间查询*/ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #define max(a,b) (a>b)?a:b #define min(a,b) (a>b)?b:a #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 100100; const int INF=0x7fffffff; using namespace std; int lazy[maxn<<2]; int SUM[maxn<<2],MAX[maxn<<2],MIN[maxn<<2]; void putup(int rt) { SUM[rt] = SUM[rt<<1] + SUM[rt<<1|1]; MAX[rt] =max(MAX[rt<<1],MAX[rt<<1|1]) ; MIN[rt] =min(MIN[rt<<1],MIN[rt<<1|1]); } void putdown(int rt,int m) { if (lazy[rt]) { lazy[rt<<1] += lazy[rt]; lazy[rt<<1|1] += lazy[rt]; SUM[rt<<1] += lazy[rt] * (m - (m >> 1)); SUM[rt<<1|1] += lazy[rt] * (m >> 1); MAX[rt<<1]+=lazy[rt]; MAX[rt<<1|1] +=lazy[rt]; MIN[rt<<1]+=lazy[rt]; MIN[rt<<1|1]+=lazy[rt]; lazy[rt] = 0; } } //以下的 l,r,rt 都带入 1,n,1 void build(int l,int r,int rt) { //初始化建树 lazy[rt] = 0; if (l == r) { //初始化树为0的写法 SUM[rt]=MAX[rt]=MIN[rt]=0; /* //边读入边建树的写法 scanf("%d",&SUM[rt]); MAX[rt]=MIN[rt]=SUM[rt]; */ return ; } int m = (l + r) >> 1; build(lson); build(rson); putup(rt); } void update(int L,int R,int v,int l,int r,int rt) { //将区间L~R的值增加v if (L <= l && r <= R) { lazy[rt] += v; SUM[rt] += v * (r - l + 1); MAX[rt]+=v; MIN[rt]+=v; return ; } putdown(rt , r - l + 1); int m = (l + r) >> 1; if (L <= m) update(L , R , v , lson); if (m < R) update(L , R , v , rson); putup(rt); } int querySUM(int L,int R,int l,int r,int rt) { //求区间L~R的和 if (L <= l && r <= R) { return SUM[rt]; } putdown(rt , r - l + 1); int m = (l + r) >> 1; int ret = 0; if (L <= m) ret += querySUM(L , R , lson); if (m < R) ret += querySUM(L , R , rson); return ret; } int queryMAX(int L,int R,int l,int r,int rt) { //求区间L~R的最大值 if (L <= l && r <= R) { return MAX[rt]; } putdown(rt , r - l + 1); int m = (l + r) >> 1; int ret = -INF; if (L <= m) ret =max(ret,queryMAX(L , R , lson)) ; if (m < R) ret =max(ret,queryMAX(L , R , rson)) ; return ret; } int queryMIN(int L,int R,int l,int r,int rt) { //求区间L~R的最小值 if (L <= l && r <= R) { return MIN[rt]; } putdown(rt , r - l + 1); int m = (l + r) >> 1; int ret = INF; if (L <= m) ret = min(ret,queryMIN(L , R , lson)); if (m < R) ret = min(ret,queryMIN(L , R , rson)); return ret; } int main() { int n , m; int a , b , c; char str[5]; scanf("%d%d",&n,&m); build(1 , n , 1); while (m--) { scanf("%s",str); if (str[0] == 'S') { scanf("%d%d",&a,&b); printf("%dn",querySUM(a , b , 1 , n , 1)); } else if(str[0]=='C') { scanf("%d%d%d",&a,&b,&c); update(a , b , c , 1 , n , 1); } else if(str[0]=='A') { scanf("%d%d",&a,&b); printf("%dn",queryMAX(a , b , 1 , n , 1)); } else if(str[0]=='I') { scanf("%d%d",&a,&b); printf("%dn",queryMIN(a , b , 1 , n , 1)); } } return 0; }

AC代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 50000+10; const int INF=0x7fffffff; int MAX[maxn<<2]; int MIN[maxn<<2]; int SUM[maxn<<2]; int str[maxn]; void PushUP(int rt) { MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]); MIN[rt] = min(MIN[rt<<1] , MIN[rt<<1|1]); SUM[rt] = SUM[rt<<1] + SUM[rt<<1|1]; } void build(int l,int r,int rt) { if (l == r) { MAX[rt] = MIN[rt] = SUM[rt] = str[l]; return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUP(rt); } void update(int p,int addv,int l,int r,int rt) { if (l == r) { SUM[rt] = SUM[rt] + addv; MIN[rt] = MIN[rt] + addv; MAX[rt] =MAX[rt]+addv; return ; } int m = (l + r) >> 1; if (p <= m) update(p , addv ,lson); else update(p , addv , rson); PushUP(rt); } int querySUM(int L,int R,int l,int r,int rt) { if (L <= l && r <= R) { return SUM[rt]; } int m = (l + r) >> 1; int ret = 0; if (L <= m) ret += querySUM(L , R , lson); if (R > m) ret += querySUM(L , R , rson); return ret; } int main(){ int n, m, score; char ch[10]; int a, b; int T; scanf("%d",&T); for(int kase = 1; kase <= T; kase++) { printf("Case %d:n", kase); scanf("%d",&n); for(int i = 1; i <= n; i++){ scanf("%d", &str[i]); } build(1, n, 1); for(;;) { scanf("%s", ch); if( ch[0] == 'E' ) break; scanf("%d%d",&a, &b); if( ch[0] == 'Q' ) printf("%dn",querySUM(a, b , 1 , n , 1)); else if( ch[0] == 'A' ) update(a , b , 1 , n , 1); else if( ch[0] == 'S' ) update(a , -b , 1 , n , 1); } } return 0; }

转载于:https://www.cnblogs.com/JinxiSui/p/9740525.html

最后

以上就是娇气裙子最近收集整理的关于HDU 1166 - 敌兵布阵 ( 线段树 )AC代码的全部内容,更多相关HDU内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部