大一集训线段树
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 }
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 }
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 }
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 }
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 }
F - Tunnel Warfare HDU - 1540
G - Disharmony Trees HDU - 3015

浙公网安备 33010602011771号