hiho_1070_RMQ
题目
区间最小值查询,但是支持对数组中的任意数字进行修改。
分析
采用RMQ_ST算法的O(1)算法不支持修改,因为每次修改都要重新设置动归数组。因此采用线段树解决,修改和查询的复杂度均为O(logN).
在实现的时候所犯的错误:每次更新一个数字的时候,走到线段树的某个节点,则直接 判断线段树的当前节点代表区间的最小值cur_min是否小于value, 如果大于则更新为value.这样做没有考虑到,当前所要更改的位置就是当前节点区间内最小值的位置,这样cur_min就无效了。
因此,还是需要从上到下找到线段树的叶子节点进行更新,之后递归返回的时候,利用子节点的min来更新父节点的min。
逻辑一定要严密!!!
实现
#include<iostream> #include<string.h> #include<iostream> #include<queue> #include<cmath> #include<unordered_map> #include<unordered_set> #include<string> #include<vector> using namespace std; const int inf = 1 << 29; const int kMax = 10005; struct Node{ int beg; int end; int min; Node(){ min = inf; } }; Node gNodes[4 * kMax]; int weight[kMax]; void BuildTree(int node, int beg, int end){ gNodes[node].beg = beg; gNodes[node].end = end; if (beg == end){ gNodes[node].min = weight[beg]; return; } int left = 2 * node + 1, right = 2 * node + 2; int mid = (beg + end) / 2; BuildTree(left, beg, mid); BuildTree(right, mid + 1, end); //更新完子节点之后,再更新父节点 gNodes[node].min = gNodes[left].min < gNodes[right].min ? gNodes[left].min : gNodes[right].min; } void Update(int node, int id, int value){ if (id < gNodes[node].beg || id > gNodes[node].end) return; if (id == gNodes[node].beg && id == gNodes[node].end){ gNodes[node].min = value; return; } int left = 2 * node + 1, right = 2 * node + 2; int mid = (gNodes[node].beg + gNodes[node].end) / 2; if (mid >= id){ Update(left, id, value); } else{ Update(right, id, value); } //更新完子节点之后,再更新父节点 gNodes[node].min = gNodes[left].min < gNodes[right].min ? gNodes[left].min : gNodes[right].min; } int Query(int node, int beg, int end){ if (gNodes[node].beg == beg && gNodes[node].end == end){ return gNodes[node].min; } int left = 2 * node + 1, right = 2 * node + 2; int mid = (gNodes[node].beg + gNodes[node].end) / 2; if (mid >= end){ return Query(left, beg, end); } else if (mid < beg){ return Query(right, beg, end); } else{ int left_min = Query(left, beg, mid); int right_min = Query(right, mid + 1, end); return left_min < right_min ? left_min : right_min; } } int main(){ int n; scanf("%d", &n); for (int i = 0; i < n; i++){ scanf("%d", &weight[i]); } BuildTree(0, 0, n - 1); scanf("%d", &n); int cmd, beg, end; for (int i = 0; i < n; i++){ scanf("%d %d %d", &cmd, &beg, &end); if (cmd == 0){ int result = Query(0, beg-1, end-1); printf("%d\n", result); } else{ Update(0, beg-1, end); } } return 0; }