大一集训线段树

A - 敌兵布阵 HDU - 1166 

 1 #include <iostream>
 2 #include <map>
 3 #include <string>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<cmath>
 7 #include<queue>
 8 using namespace std;
 9 const int maxn = 500005 * 4;    //线段树范围要开4倍
10 struct Tree
11 {
12     int l, r, sum, maxx;
13 };
14 Tree node[maxn];        //node[maxn]为线段树处理数组
15 int a[maxn];            //a[maxn]为原数组
16 void PushUp(int i)
17 {
18     node[i].sum = node[i << 1].sum + node[(i << 1) | 1].sum;//                    i<<1 就是i*2,(i << 1) | 1就是i*2+1
19     node[i].maxx = max(node[i << 1].maxx, node[(i << 1) | 1].maxx);
20 }
21 void build(int i, int l, int r)//构建树
22 {
23     node[i].l = l; node[i].r = r;
24     if (l == r)
25     {
26         node[i].maxx = a[l];
27         node[i].sum = a[l];
28         return;
29     }
30     int mid = (l + r) / 2;
31     build(i << 1, l, mid);
32     build((i << 1) | 1, mid + 1, r);
33     PushUp(i);
34 }
35 int getsum(int i, int l, int r)//求和
36 {
37     if (node[i].l == l && node[i].r == r)
38         return node[i].sum;
39     int mid = (node[i].l + node[i].r) / 2;
40     if (r <= mid) return getsum(i << 1, l, r);
41     else if (l > mid) return getsum((i << 1) | 1, l, r);
42     else return getsum(i << 1, l, mid) + getsum((i << 1) | 1, mid + 1, r);
43 }
44 int getmax(int i, int l, int r)//求最大值
45 {
46     if (node[i].l == l && node[i].r == r)
47         return node[i].maxx;
48     int mid = (node[i].l + node[i].r) / 2;
49     if (r <= mid) return getmax(i << 1, l, r);
50     else if (l > mid) return getmax((i << 1) | 1, l, r);
51     else return max(getmax(i << 1, l, mid), getmax((i << 1) | 1, mid + 1, r));
52 }
53 void add(int i, int k, int v)            //当前更新的节点的编号为i(一般是1为初始编号,具体得看建立树时使用的第一个编号是什么)。
54 {                                //k为需要更新的点的位置,v为修改的值的大小
55     if (node[i].l == k && node[i].r == k)        //左右端点均和k相等,说明找到了k所在的叶子节点
56     {
57         node[i].sum += v;
58         node[i].maxx += v;
59         return;    //找到了叶子节点就不需要在向下寻找了
60     }
61     int mid = (node[i].l + node[i].r) / 2;
62     if (k <= mid) add(i << 1, k, v);
63     else add((i << 1) | 1, k, v);
64     PushUp(i);
65 }
66 int main() {
67     int t;
68     scanf("%d", &t);
69     for (int k = 0;k < t;k++) {
70         memset(a, 0, sizeof(a));
71         printf("Case %d:\n", k+1);
72         int n;
73         scanf("%d", &n);
74         for (int i = 1;i <=n;i++) {
75             scanf("%d", &a[i]);
76         }
77         build(1, 1, n);
78         string s;
79         int num1, num2;
80         while (cin >> s) {
81             if (s[0] == 'E')break;
82             scanf("%d %d", &num1, &num2);
83             //if (s[0] == 'E')break;
84              if (s[0] == 'Q') {
85                 printf("%d\n",getsum(1, num1, num2));
86             }
87             else if (s[0] == 'A') {
88                 add(1, num1, num2);
89                 //printf("%d\n", getsum(1, num1, num1));
90             }
91             else if (s[0] == 'S') {
92                 add(1, num1, -num2);
93                 //printf("%d\n", getsum(1, num1, num1));
94             }
95         }
96     }
97 }
View Code

B - I Hate It HDU - 1754 

 1 #include <iostream>
 2 #include <map>
 3 #include <string>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<cmath>
 7 #include<queue>
 8 using namespace std;
 9 const int maxn = 500005 * 4;    //线段树范围要开4倍
10 struct Tree
11 {
12     int l, r, sum, maxx,val;
13 };
14 Tree node[maxn];        //node[maxn]为线段树处理数组
15 int arr[maxn];            //a[maxn]为原数组
16 void PushUp(int i)
17 {
18     node[i].sum = node[i << 1].sum + node[(i << 1) | 1].sum;//                    i<<1 就是i*2,(i << 1) | 1就是i*2+1
19     node[i].maxx = max(node[i << 1].maxx, node[(i << 1) | 1].maxx);
20 }
21 void build(int i, int l, int r)//构建树
22 {
23     node[i].l = l; node[i].r = r;
24     if (l == r)
25     {
26         node[i].maxx = arr[l];
27         node[i].sum = arr[l];
28         node[i].val = arr[l];
29         return;
30     }
31     int mid = (l + r) / 2;
32     build(i << 1, l, mid);
33     build((i << 1) | 1, mid + 1, r);
34     PushUp(i);
35 }
36 int getsum(int i, int l, int r)//求和
37 {
38     if (node[i].l == l && node[i].r == r)
39         return node[i].sum;
40     int mid = (node[i].l + node[i].r) / 2;
41     if (r <= mid) return getsum(i << 1, l, r);
42     else if (l > mid) return getsum((i << 1) | 1, l, r);
43     else return getsum(i << 1, l, mid) + getsum((i << 1) | 1, mid + 1, r);
44 }
45 int getmax(int i, int l, int r)//求最大值
46 {
47     if (node[i].l == l && node[i].r == r)
48         return node[i].maxx;
49     int mid = (node[i].l + node[i].r) / 2;
50     if (r <= mid) return getmax(i << 1, l, r);
51     else if (l > mid) return getmax((i << 1) | 1, l, r);
52     else return max(getmax(i << 1, l, mid), getmax((i << 1) | 1, mid + 1, r));
53 }
54 void add(int i, int k, int v)            //当前更新的节点的编号为i(一般是1为初始编号,具体得看建立树时使用的第一个编号是什么)。
55 {                                //k为需要更新的点的位置,v为修改的值的大小
56     if (node[i].l == k && node[i].r == k)        //左右端点均和k相等,说明找到了k所在的叶子节点
57     {
58         node[i].sum += v;
59         node[i].maxx += v;
60         return;    //找到了叶子节点就不需要在向下寻找了
61     }
62     int mid = (node[i].l + node[i].r) / 2;
63     if (k <= mid) add(i << 1, k, v);
64     else add((i << 1) | 1, k, v);
65     PushUp(i);
66 }
67 void update(int i, int k, int v)            
68 {                            
69     if (node[i].l == k && node[i].r == k)        
70     {
71         node[i].maxx = v;
72         return;    
73     }
74     int mid = (node[i].l + node[i].r) / 2;
75     if (k <= mid) update(i << 1, k, v);
76     else update((i << 1) | 1, k, v);
77     PushUp(i);
78 }
79 int main() {
80     int n, m;
81     while (scanf("%d %d", &n, &m) != EOF) {
82         memset(arr, 0, sizeof(arr));
83         for (int i = 1;i <= n;i++) {
84             scanf("%d", &arr[i]);
85         }
86         build(1, 1, n);
87         string s;
88         int num1, num2;
89         for (int i = 0;i < m;i++) {
90             cin >> s >> num1 >> num2;
91             if (s[0] == 'Q') {
92                 printf("%d\n", getmax(1, num1, num2));
93             }
94             else { update(1, num1, num2); }
95         }
96     }
97 }
View Code

C - Potentiometers UVA - 12086 

  1 #include <iostream>
  2 #include <map>
  3 #include <string>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<cmath>
  7 #include<queue>
  8 using namespace std;
  9 const int maxn = 500005 * 4;    //线段树范围要开4倍
 10 struct Tree
 11 {
 12     int l, r, sum, maxx;
 13 };
 14 Tree node[maxn];        //node[maxn]为线段树处理数组
 15 int arr[maxn];            //a[maxn]为原数组
 16 void PushUp(int i)
 17 {
 18     node[i].sum = node[i << 1].sum + node[(i << 1) | 1].sum;//                    i<<1 就是i*2,(i << 1) | 1就是i*2+1
 19     node[i].maxx = max(node[i << 1].maxx, node[(i << 1) | 1].maxx);
 20 }
 21 void build(int i, int l, int r)//构建树
 22 {
 23     node[i].l = l; node[i].r = r;
 24     if (l == r)
 25     {
 26         node[i].maxx = arr[l];
 27         node[i].sum = arr[l];
 28         return;
 29     }
 30     int mid = (l + r) / 2;
 31     build(i << 1, l, mid);
 32     build((i << 1) | 1, mid + 1, r);
 33     PushUp(i);
 34 }
 35 int getsum(int i, int l, int r)//求和
 36 {
 37     if (node[i].l == l && node[i].r == r)
 38         return node[i].sum;
 39     int mid = (node[i].l + node[i].r) / 2;
 40     if (r <= mid) return getsum(i << 1, l, r);
 41     else if (l > mid) return getsum((i << 1) | 1, l, r);
 42     else return getsum(i << 1, l, mid) + getsum((i << 1) | 1, mid + 1, r);
 43 }
 44 int getmax(int i, int l, int r)//求最大值
 45 {
 46     if (node[i].l == l && node[i].r == r)
 47         return node[i].maxx;
 48     int mid = (node[i].l + node[i].r) / 2;
 49     if (r <= mid) return getmax(i << 1, l, r);
 50     else if (l > mid) return getmax((i << 1) | 1, l, r);
 51     else return max(getmax(i << 1, l, mid), getmax((i << 1) | 1, mid + 1, r));
 52 }
 53 void add(int i, int k, int v)            //当前更新的节点的编号为i(一般是1为初始编号,具体得看建立树时使用的第一个编号是什么)。
 54 {                                //k为需要更新的点的位置,v为修改的值的大小
 55     if (node[i].l == k && node[i].r == k)        //左右端点均和k相等,说明找到了k所在的叶子节点
 56     {
 57         node[i].sum += v;
 58         node[i].maxx += v;
 59         return;    //找到了叶子节点就不需要在向下寻找了
 60     }
 61     int mid = (node[i].l + node[i].r) / 2;
 62     if (k <= mid) add(i << 1, k, v);
 63     else add((i << 1) | 1, k, v);
 64     PushUp(i);
 65 }
 66 void update(int i, int k, int v)            
 67 {                            
 68     if (node[i].l == k && node[i].r == k)        
 69     {
 70         node[i].maxx = v;
 71         node[i].sum = v;
 72         return;    
 73     }
 74     int mid = (node[i].l + node[i].r) / 2;
 75     if (k <= mid) update(i << 1, k, v);
 76     else update((i << 1) | 1, k, v);
 77     PushUp(i);
 78 }
 79 int main() {
 80     int n;
 81     int add = 1;
 82     while (scanf("%d", &n),n) {
 83         if (add != 1)printf("\n");
 84         printf("Case %d:\n", add);
 85         //memset(arr, 0, sizeof(arr));
 86         for (int i = 1;i <= n;i++) {
 87             scanf("%d", &arr[i]);
 88         }
 89         build(1, 1, n);
 90         string s;
 91         while (cin >> s) {
 92             if (s[0] == 'E')break;
 93             int num1, num2;
 94             scanf("%d %d", &num1, &num2);
 95             if (s[0] == 'M') {
 96                     printf("%d\n", getsum(1, num1, num2));
 97                 }
 98             else { update(1, num1, num2); }
 99             }
100         
101         add++;
102         
103     }
104 }
View Code

D - Just a Hook HDU - 1698 线段树批量更新

  1 #include <iostream>
  2 #include <map>
  3 #include <string>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<cmath>
  7 #include<queue>
  8 using namespace std;
  9 //const int maxn = 500005 * 4;    //线段树范围要开4倍
 10 const int N = 100005;
 11 long long arr[N];                    //a[N]储存原数组
 12 long long  lazy[N << 2];            //lazy用来记录该节点的每个数值应该加多少 
 13 int n, q;
 14 struct Tree
 15 {
 16     int l, r;
 17     long long sum;
 18     int mid()
 19     {
 20         return (l + r) >> 1;
 21     }
 22 }tree[N << 2];
 23 
 24 void PushUp(int rt)
 25 {
 26     tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
 27 }
 28 
 29 void PushDown(int rt, int m)//给lazy数组赋值,改变tree数组的值
 30 {
 31     if (lazy[rt])
 32     {
 33         lazy[rt << 1] = lazy[rt];////////
 34         lazy[rt << 1 | 1] = lazy[rt];///////
 35         tree[rt << 1].sum = lazy[rt] * (m - (m >> 1));/////
 36         tree[rt << 1 | 1].sum = lazy[rt] * (m >> 1);//////
 37         lazy[rt] = 0;
 38     }
 39 }
 40 
 41 void build(int l, int r, int rt)
 42 {
 43     tree[rt].l = l;
 44     tree[rt].r = r;
 45     lazy[rt] = 0;
 46     if (l == r)
 47     {
 48         tree[rt].sum = arr[l];
 49         return;
 50     }
 51     int m = tree[rt].mid();
 52     build(l, m, (rt << 1));
 53     build(m + 1, r, (rt << 1 | 1));
 54     PushUp(rt);
 55 }
 56 
 57 void update(long long c, int l, int r, int rt)
 58 {
 59     if (tree[rt].l == l && tree[rt].r == r)
 60     {
 61         lazy[rt] = c;///////
 62         tree[rt].sum = c * (r - l + 1);/////////////
 63         return;
 64     }
 65     if (tree[rt].l == tree[rt].r)return;
 66     int m = tree[rt].mid();
 67     PushDown(rt, tree[rt].r - tree[rt].l + 1);
 68     if (r <= m)update(c, l, r, rt << 1);
 69     else if (l > m)update(c, l, r, rt << 1 | 1);
 70     else
 71     {
 72         update(c, l, m, rt << 1);
 73         update(c, m + 1, r, rt << 1 | 1);
 74     }
 75     PushUp(rt);
 76 }
 77 long long Query(int l, int r, int rt)
 78 {
 79     if (l == tree[rt].l && r == tree[rt].r)
 80     {
 81         return tree[rt].sum;
 82     }
 83     int m = tree[rt].mid();
 84     PushDown(rt, tree[rt].r - tree[rt].l + 1);
 85     long long res = 0;
 86     if (r <= m)res += Query(l, r, rt << 1);
 87     else if (l > m)res += Query(l, r, rt << 1 | 1);
 88     else
 89     {
 90         res += Query(l, m, rt << 1);
 91         res += Query(m + 1, r, rt << 1 | 1);
 92     }
 93     return res;
 94 }
 95 int main() {
 96     int n;
 97     int add = 1;
 98     scanf("%d", &n);
 99     for(int k=1;k<=n;k++){
100         memset(lazy, 0, sizeof lazy);
101         int len;
102         scanf("%d", &len);
103         int time;
104         scanf("%d", &time);
105         for (int i = 1;i <= len;i++) {arr[i] = 1;}
106         build(1, len, 1);
107         while (time--) {
108             int x, y, z;
109             scanf("%d %d %d", &x, &y, &z);
110             Query(x, y, 1);
111             update(z, x, y, 1);
112         }
113         printf("Case %d: The total value of the hook is %d.\n", k, tree[1].sum);
114 
115     }
116 }
View Code

 

E - Xenia and Bit Operations CodeForces - 339D

题意:给定n和m,给你一个包含2^n个数的数组,有m次操作,每次操作先将p位置的数修改,先两两相或使数组减少一半,再两两相异或使数组再减少一半,一直重复这两种操作,直到数组剩余一个元素。

  1 #include <iostream>
  2 #include <map>
  3 #include <string>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<cmath>
  7 #include<queue>
  8 using namespace std;
  9 const int maxn = 500005 * 4;    //线段树范围要开4倍
 10 int deep[maxn];
 11 struct Tree
 12 {
 13     int l, r, sum, maxx;
 14 };
 15 Tree node[maxn];        //node[maxn]为线段树处理数组
 16 long long int arr[maxn];            //a[maxn]为原数组
 17 void PushUp(int i)
 18 {
 19     if (deep[i*2]==1) {
 20         deep[i] = 0;
 21         node[i].sum = node[i << 1].sum | node[(i << 1) | 1].sum;//                    i<<1 就是i*2,(i << 1) | 1就是i*2+1
 22         node[i].maxx = max(node[i << 1].maxx, node[(i << 1) | 1].maxx);
 23     }
 24     else{
 25         deep[i] = 1;
 26         node[i].sum = node[i << 1].sum ^ node[(i << 1) | 1].sum;//                    i<<1 就是i*2,(i << 1) | 1就是i*2+1
 27         node[i].maxx = max(node[i << 1].maxx, node[(i << 1) | 1].maxx);
 28     }
 29 }
 30 void build(int i, int l, int r)//构建树
 31 {
 32     node[i].l = l; node[i].r = r;
 33     if (l == r)
 34     {
 35         deep[i] = 1;
 36         node[i].maxx = arr[l];
 37         node[i].sum = arr[l];
 38         return;
 39     }
 40     int mid = (l + r) / 2;
 41     build(i << 1, l, mid);
 42     build((i << 1) | 1, mid + 1, r);
 43     PushUp(i);
 44 }
 45 int getsum(int i, int l, int r)//求和
 46 {
 47     if (node[i].l == l && node[i].r == r)
 48         return node[i].sum;
 49     int mid = (node[i].l + node[i].r) / 2;
 50     if (r <= mid) return getsum(i << 1, l, r);
 51     else if (l > mid) return getsum((i << 1) | 1, l, r);
 52     else return getsum(i << 1, l, mid) + getsum((i << 1) | 1, mid + 1, r);
 53 }
 54 int getmax(int i, int l, int r)//求最大值
 55 {
 56     if (node[i].l == l && node[i].r == r)
 57         return node[i].maxx;
 58     int mid = (node[i].l + node[i].r) / 2;
 59     if (r <= mid) return getmax(i << 1, l, r);
 60     else if (l > mid) return getmax((i << 1) | 1, l, r);
 61     else return max(getmax(i << 1, l, mid), getmax((i << 1) | 1, mid + 1, r));
 62 }
 63 void add(int i, int k, int v)            //当前更新的节点的编号为i(一般是1为初始编号,具体得看建立树时使用的第一个编号是什么)。
 64 {                                //k为需要更新的点的位置,v为修改的值的大小
 65     if (node[i].l == k && node[i].r == k)        //左右端点均和k相等,说明找到了k所在的叶子节点
 66     {
 67         node[i].sum += v;
 68         node[i].maxx += v;
 69         return;    //找到了叶子节点就不需要在向下寻找了
 70     }
 71     int mid = (node[i].l + node[i].r) / 2;
 72     if (k <= mid) add(i << 1, k, v);
 73     else add((i << 1) | 1, k, v);
 74     PushUp(i);
 75 }
 76 void update(int i, int k, int v)
 77 {
 78     if (node[i].l == k && node[i].r == k)
 79     {
 80         node[i].maxx = v;
 81         node[i].sum = v;
 82         return;
 83     }
 84     int mid = (node[i].l + node[i].r) / 2;
 85     if (k <= mid) update(i << 1, k, v);
 86     else update((i << 1) | 1, k, v);
 87     PushUp(i);
 88 }
 89 int main() {
 90     int n, m;
 91     scanf("%d %d", &n, &m);
 92     int realn = pow(2, n);
 93     for (int i = 1;i <= realn;i++) {
 94         scanf("%lld", &arr[i]);
 95     }
 96     build(1, 1, realn);
 97     for (int i = 0;i <m;i++) {
 98         int a, b;
 99         scanf("%d %d", &a, &b);
100         
101         update(1, a, b);
102         
103         printf("%d\n", node[1].sum);
104     }
105 }
View Code

F - Tunnel Warfare HDU - 1540 

G - Disharmony Trees HDU - 3015 

posted @ 2020-02-19 17:00  programmer_w  阅读(0)  评论(0)    收藏  举报