这里说的是单点修改.
模板题
不同于RMQ,RMQ修改后再去处理,复杂度就会很高. 而线段树修改和询问都还是会保持在logn的复杂度之内.
AC Code 和 板子: (求区间最大,最小,区间和稍微修改下就行了, 如果有多种东西(比如说有lazy标记, 或者同时维护多种关系等)要存,直接在结构体中添加相应的元素即可,然后修改一些地方的判断)
//直接用就行了.
const int maxn = 1e6+5;
int n, a[maxn];
struct Tree {
int tl, tr;
int minn, maxx;
}tree[maxn<<2];
void pushup(int id) {
tree[id].minn = min(tree[id<<1].minn , tree[id<<1|1].minn);
tree[id].maxx = max(tree[id<<1].maxx , tree[id<<1|1].maxx);
}
void build(int id, int l, int r) {
tree[id].tl = l, tree[id].tr = r;
if(l == r) {
tree[id].maxx = tree[id].minn = a[l];
return ;
}
int mid = (r+l)>>1;
build(id<<1, l, mid);
build(id<<1|1, mid+1, r);
pushup(id);
}
void update(int id, int pos, int val) {
int l = tree[id].tl, r = tree[id].tr;
if(l == r) {
tree[id].maxx = tree[id].minn = val;
return ;
}
int mid = (l+r) >> 1;
if(pos <= mid) update(id<<1, pos, val);
else update(id<<1|1, pos, val);
pushup(id);
}
int querymi(int id, int ql, int qr) {
int l = tree[id].tl, r = tree[id].tr;
if(ql <= l && r <= qr ){
return tree[id].minn;
}
int mid = (l + r) >> 1;
if(qr <= mid) return querymi(id<<1, ql, qr);
else if(ql > mid) return querymi(id<<1|1, ql, qr);
else return min(querymi(id<<1, ql, mid), querymi(id<<1|1, mid+1, qr));
}
int querymx(int id, int ql, int qr) {
int l = tree[id].tl, r = tree[id].tr;
if(ql <= l && r <= qr ){
return tree[id].maxx;
}
int mid = (l + r) >> 1;
if(qr <= mid) return querymx(id<<1, ql, qr);
else if(ql > mid) return querymx(id<<1|1, ql, qr);
else return max(querymx(id<<1, ql, mid), querymx(id<<1|1, mid+1, qr));
}
void solve() {
scanf("%d",&n);
for(int i = 1 ; i <= n ; i ++) {
scanf("%d",&a[i]);
}
build(1, 1, n);
int q; scanf("%d",&q);
while(q--){
int op, l, r;
scanf("%d%d%d",&op, &l, &r);
if(!op) printf("%d\n",querymi(1, l, r)); //或者是mx.
else update(1, l, r);
}
}
区间更新中的单点更新模板: (该出代码对应的问题) 类似问题 HDU 4027 (区间开根问题, 注意就是输入数据会有l > r的情况).
// 这类题都是套路题, 每个点被修改的次数不会太多次.
const int maxn = 3e5 + 5;
const int maxm = 1e6 + 5;
int cas=1;
int d[maxm];
void init() {
for (int i = 1 ; i <= 1000000 ; i ++) {
for (int j = i ; j <= 1000000 ; j += i) {
d[j]++;
}
}
}
ll a[maxn];
struct Tree
{
int tl, tr; ll val, mx;
}tree[maxn<<2];
void pushup(int id)
{
tree[id].val = tree[id<<1].val + tree[id<<1|1].val;
tree[id].mx = max(tree[id<<1].mx, tree[id<<1|1].mx);
}
void build(int id, int l, int r) {
tree[id].tl = l, tree[id].tr = r;
if(l == r) {
tree[id].val = tree[id].mx = a[l];
return ;
}
int mid = (r+l)>>1;
build(id<<1, l, mid);
build(id<<1|1, mid+1, r);
pushup(id);
}
void update(int id, int ul, int ur) {
int l = tree[id].tl, r = tree[id].tr;
if (ul <= l && r <= ur && tree[id].mx <= 2) return ;
// 关键剪枝, 不同的题目这里写的不同, 维护的东西也不同. 由题来定.
if(l == r){
tree[id].val = tree[id].mx = d[a[l]];
a[l] = d[a[l]];
return ;
}
int mid = (l+r) >> 1;
if (ul <= mid) update(id<<1, ul, ur);
if (ur > mid) update(id<<1|1, ul, ur);
pushup(id);
}
ll query(int id, int ql, int qr) {
int l = tree[id].tl , r = tree[id].tr;
if(ql <= l && r <= qr) {
return tree[id].val;
}
int mid = (l+r) >> 1 ;
if(qr <= mid) return query(id<<1, ql, qr);
else if(ql > mid) return query(id<<1|1, ql, qr);
else return query(id<<1, ql, mid) + query(id<<1|1, mid+1, qr);
}
void solve() {
int n, q; init();
scanf("%d%d",&n, &q);
for(int i = 1 ; i <= n ; i ++) {
scanf("%lld", &a[i]);
}
build(1, 1, n);
while(q--){
int op, l, r;
scanf("%d%d%d",&op, &l, &r);
if(op == 1) update(1, l, r);
else printf("%lld\n", query(1, l, r));
}
}