线段树单点更新_ACM模板
题目描述
第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。学生ID编号分别从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
接下来有M行。每一行有一个字符 C (只取’Q’或’U’) ,和两个正整数A,B。
当C为’Q’的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少?
当C为’U’的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。
const int maxn = int(1e5) * 2;//N的上限
int a[maxn];//a[i]:id为i的学生的成绩。
struct node {
int l, r;//节点的左界、右界
int n;//节点的值(最大值)
}s[maxn * 4];
void bulid(int l, int r, int k) {//创建线段树
s[k].l = l;
s[k].r = r;
if (l == r) {
s[k].n = a[l];
return;
}
int mid = (l + r) / 2;
bulid(l, mid, 2 * k);
bulid(mid + 1, r, 2 * k + 1);
s[k].n = max(s[k * 2].n, s[k * 2 + 1].n);
}
void update(int d, int n, int k) {//更新:将id为i的成绩改成n
if (s[k].l == d && d == s[k].r) {
s[k].n = n;
return;
}
int mid = (s[k].l + s[k].r) / 2;
if (d <= mid) {
update(d, n, 2 * k);
}
else {
update(d, n, 2 * k + 1);
}
s[k].n = max(s[k * 2].n, s[k * 2 + 1].n);
}
int fin(int l, int r, int k) {//返回[l,r]区间的最大值
int ans;
if (s[k].l == l && s[k].r == r) {
return s[k].n;
}
int mid = (s[k].l + s[k].r) / 2;
if (r <= mid) {
ans=fin(l, r, 2 * k);
}
else if (mid < l) {
ans=fin(l, r, 2 * k + 1);
}
else {
ans = max(fin(l, mid, 2 * k), fin(mid + 1, r, 2 * k + 1));
}
return ans;
}