Find the smallest value in part of a list, while the list keeps changing.
What to build
A segment tree that stores minimums instead of sums.
Requirements
M l rprints the smallest ofa[l]toa[r].U i vchangesa[i]tov.- Both operations must take O(log n).
Input
The first line has n and q. The second line has the n numbers. Each of the next q lines has one operation. Positions start at 0.
Output
One line for each M.
Constraints
1 ≤ n, q ≤ 1000, 0 ≤ l ≤ r < n, and every value is from −1 000 000 to 1 000 000.
Example
Input:
5 4
5 8 6 3 2
M 0 2
M 1 4
U 4 9
M 1 4
Output:
5
2
3
Why it works
A segment tree only needs a way to combine the answers of two halves, and "the smaller of the two" works as well as "the sum". Prefix tricks fail here, because one minimum cannot be subtracted from another.
Examples
5 4 5 8 6 3 2 M 0 2 M 1 4 U 4 9 M 1 4
5 2 3
1 2 4 M 0 0 U 0 -1
4
Hints
Hint 1
The starter is the lesson's tree of sums. Each node must store the smaller of its two children instead of their total.
Hint 2
A node outside the question must not affect the answer. Returning 0, as the sum tree does, would be wrong.
Hint 3
One way round that: only go into a half that the question actually reaches.
Solution
Show one correct solution (try it yourself first)
#include <stdio.h>
int a[1000], tree[4000];
int smaller(int x, int y) {
return x < y ? x : y;
}
void build(int node, int lo, int hi) {
if (lo == hi) {
tree[node] = a[lo];
return;
}
int mid = (lo + hi) / 2;
build(2 * node, lo, mid);
build(2 * node + 1, mid + 1, hi);
tree[node] = smaller(tree[2 * node], tree[2 * node + 1]);
}
int query(int node, int lo, int hi, int l, int r) {
if (l <= lo && hi <= r) return tree[node];
int mid = (lo + hi) / 2;
if (r <= mid) return query(2 * node, lo, mid, l, r); /* only the left half is asked about */
if (l > mid) return query(2 * node + 1, mid + 1, hi, l, r); /* only the right half */
return smaller(query(2 * node, lo, mid, l, r), query(2 * node + 1, mid + 1, hi, l, r));
}
void update(int node, int lo, int hi, int i, int value) {
if (lo == hi) {
tree[node] = value;
return;
}
int mid = (lo + hi) / 2;
if (i <= mid) update(2 * node, lo, mid, i, value);
else update(2 * node + 1, mid + 1, hi, i, value);
tree[node] = smaller(tree[2 * node], tree[2 * node + 1]);
}
int main(void) {
int n, q;
scanf("%d %d", &n, &q);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
build(1, 0, n - 1);
for (int k = 0; k < q; k++) {
char op[2];
int x, y;
scanf("%1s %d %d", op, &x, &y);
if (op[0] == 'M') printf("%d\n", query(1, 0, n - 1, x, y));
else update(1, 0, n - 1, x, y);
}
return 0;
}