简单线段树基本操作。
线段树是一种树状结构,每个结点对应了一个区间,由于该结构是一个典型的二叉树,所以每一层最多只会递归两次,假定根结点长度为pow(2,h),那么结点总数容易计算出来,大约区间长度的两倍,很多人说要开四倍的数组,这其实是针对于非递归写法的,如果用递归写只需要开三倍就够了。
其实递归手法很巧妙的,用返回值顺带更新了所有祖先结点。
细节参见代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 1000000000;
const int maxn = 200000 + 5;
int a,n,m,maxv[3*maxn],ql,qr,p,v;
int query(int o, int L, int R) {
int M = L + (R-L)/2, ans = -1;
if(ql <= L && qr >= R) return maxv[o];
if(ql <= M) ans = max(ans, query(o*2, L, M));
if(qr > M) ans = max(ans, query(o*2+1, M+1, R));
return ans;
}
void update(int o, int L, int R) {
int M = L + (R-L)/2;
if(L == R) maxv[o] = v;
else {
if(p <= M) update(o*2, L, M); else update(o*2+1, M+1, R);
maxv[o] = max(maxv[o*2], maxv[o*2+1]);
}
}
char s[10];
int main() {
while(~scanf("%d%d",&n,&m)) {
for(int i=1;i<=n;i++) {
scanf("%d",&a);
p = i; v = a;
update(1,1,n);
}
while(m--) {
scanf("%s%d%d",s,&ql,&qr);
if(s[0] == 'U') {
p = ql; v = qr;
update(1,1,n);
}
else {
printf("%d\n",query(1,1,n));
}
}
}
return 0;
}