题意:给一串序列,有两种操作:更新某点x序列值为y;求区间[x, y]内序列最大值
思路:线段树模版题,建立线段树,节点值为该区间内最大值,更新时递归更新保证父亲节点在子节点更新后得到更新,查询时若查询区间完全包含当前区间,则返回当前区间值,否则返回两个子区间的最大值。在递归求子区间最大值时,需要判断当前区间是否与查询区间相交,只有相交时才继续递归。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
const int inf = 0x3f3f3f3f;
int n, m, a[maxn], tree[maxn];
void build(int root, int l, int r)
{
if (l == r) {
tree[root] = a[l];
return;
}
int mid = (l+r)>>1;
build(root<<1, l, mid);
build(root<<1|1, mid+1, r);
tree[root] = max(tree[root<<1], tree[root<<1|1]);
}
void update(int k, int x, int l, int r, int root)
{
if (l == r) {
tree[root] = x;
return;
}
int mid = (l+r)>>1;
if (k <= mid) {
update(k, x, l, mid, root<<1);
}
else {
update(k, x, mid+1, r, root<<1|1);
}
tree[root] = max(tree[root<<1], tree[root<<1|1]);
}
int query(int root, int x, int y, int l, int r)
{
if (r < x || l > y)
return 0;
if (x <= l && y >= r)
return tree[root];
int mid = (l+r)>>1;
return max(query(root<<1, x, y, l, mid), query(root<<1|1, x, y, mid+1, r));
}
int main()
{
while (~scanf("%d%d", &n, &m)) {
memset(tree, 0, sizeof(tree));
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, 1, n);
for (int i = 1; i <= m; i++) {
char c;
int x, y;
scanf(" %c%d%d", &c, &x, &y);
if (c == 'Q') {
printf("%d\n", query(1, x, y, 1, n));
}
if (c == 'U') {
update(x, y, 1, n, 1);
}
}
}
}