Hdu【线段树】基础题.cpp

[1166 敌兵布阵]

题意:

  给出一些命令..要求可以:

    随时增加或减少某个位置上的数

    随时查询某段区间上的和..

  输入:

  一个T 表示有T组样例

  每组样例一个n 表示有n个位置

  输入命令:

    Add a b 表示在 a 位置上增加 b

    Sub a b 表示在 a 位置上减少 b

    Query a b 表示求 a 到 b 的和

 

思路:

  因为数据量很大..所以无法靠暴力来遍历求和..

  所以用线段树..

 

Tips:

  更新的时候注意sum数组开到节点的4倍

 

Code:

View Code
 1 #include <stdio.h>
 2 #include <cstring>
 3 
 4 const int MAXN = 50010;
 5 int a[MAXN], sum[MAXN*4];
 6 
 7 void creat(int l, int r, int rt)
 8 {
 9     if(l == r) {
10         scanf("%d", &sum[rt]);
11         return;
12     }
13     int m = (l+r)>>1;
14     creat(l, m, rt<<1);
15     creat(m+1, r, rt<<1|1);
16     sum[rt] = sum[rt<<1]+sum[rt<<1|1];
17 }
18 
19 void update(int p, int w, int l, int r, int rt)
20 {
21     if(l == r) {
22         sum[rt] += w;
23         return;
24     }
25     int m = (l+r)>>1;
26     if(p <= m) update(p, w, l, m, rt<<1);
27     else update(p, w, m+1, r, rt<<1|1);
28     sum[rt] = sum[rt<<1]+sum[rt<<1|1];
29 }
30 
31 int query(int l, int r, int L, int R, int rt)
32 {
33     if(l <= L && R <= r) {
34         return sum[rt];
35     }
36     int m = (L+R)>>1;
37     int res = 0;
38     if(l <= m) res += query(l, r, L, m, rt<<1);
39     if(r > m) res += query(l, r, m+1, R, rt<<1|1);
40     return res;
41 }
42 
43 int main()
44 {
45     int i, j, k = 0;
46     int T, n;
47     char opt[10];
48     int a, b;
49     while(scanf("%d", &T) != EOF)
50     while(T--)
51     {
52         printf("Case %d:\n", ++k);
53         scanf("%d", &n);
54         creat(1, n, 1);
55         while(scanf("%s", opt), opt[0] != 'E') {
56             scanf("%d %d", &a, &b);
57             if(opt[0] == 'A')
58                 update(a, b, 1, n, 1);
59             else if(opt[0] == 'S')
60                 update(a, -1*b, 1, n, 1);
61             else if(opt[0] == 'Q')
62                 printf("%d\n", query(a, b, 1, n, 1));
63         }
64 
65     }
66     return 0;
67 }

 

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

 

[1754 i hate it]

题意:

  给出一些数值根据命令更新或查询区间最大值

思路:

  向上更新的时候找最大值

Tips:

  可以用函数实现更新操作

Code:

  

View Code
 1 #include <stdio.h>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int MAXN = 200010;
 7 int ma[MAXN<<2];
 8 
 9 void creat(int l, int r, int rt)
10 {
11     if(l == r) {
12         scanf("%d", &ma[rt]);
13         return;
14     }
15     int mid = (l+r)>>1;
16     creat(l, mid, rt<<1);
17     creat(mid+1, r, rt<<1|1);
18     ma[rt] = max(ma[rt<<1], ma[rt<<1|1]);
19 }
20 
21 void modify(int p, int w, int l, int r, int rt)
22 {
23     if(l == r) {
24         ma[rt] = w;
25         return;
26     }
27     int mid = (l+r)>>1;
28     if(p <= mid) modify(p, w, l, mid, rt<<1);
29     else modify(p, w, mid+1, r, rt<<1|1);
30     ma[rt] = max(ma[rt<<1], ma[rt<<1|1]);
31 }
32 
33 int query(int l, int r, int L, int R, int rt)
34 {
35     if(l <= L && r >= R) {
36         return ma[rt];
37     }
38     int mid = (L+R)>>1;
39     int res = 0;
40     if(l <= mid) res = max(res, query(l, r, L, mid, rt<<1));
41     if(r > mid) res = max(res, query(l, r, mid+1, R, rt<<1|1));
42     return res;
43 }
44 
45 int main()
46 {
47     int i, j, k;
48     int n, m;
49     char opt[2];
50     int a, b;
51     while(scanf("%d %d", &n, &m) != EOF)
52     {
53         creat(1, n, 1);
54         while(m--) {
55             scanf("%s", &opt);
56             scanf("%d %d", &a, &b);
57             if(opt[0] == 'Q')
58                 printf("%d\n", query(a, b, 1, n, 1));
59             else if(opt[0] == 'U') modify(a, b, 1, n, 1);
60         }
61     }
62     return 0;
63 }

 

 

 

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

posted @ 2012-10-09 21:12  Griselda.  阅读(326)  评论(0编辑  收藏  举报