线段树模板

线段树2020

单点更新,区间查询,维护区间和

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6+10;
int n,m,a[N];
int sumv[N<<2];

//合并 
void pushup(int o){
	sumv[o] = sumv[o<<1] + sumv[o<<1|1];
}

//建树 
void build(int o,int l,int r){
	if(l == r) { //到最后一行了 [1,1] [2,2] ... 
		sumv[o] = a[l];
		return;
	}
	int mid = (l+r)>>1; 
	build(o<<1,l,mid);
	build(o<<1|1,mid+1,r);
	pushup(o);//向上合并 
}

//a[x] += y : change(1,1,n,x,y); 
//单点修改  o为当前到达节点的编号 
void change(int o,int l,int r,int pos,int v){
	if(l == r){
		sumv[o] += v;
		return;
	}	
	int mid = (l+r)>>1;
	if(pos <= mid) change(o<<1,l,mid,pos,v);//前半段区间
	else change(o<<1|1,mid+1,r,pos,v); //后半段区间
	pushup(o); //向上更新  有一些线段树维护了多个值,所以pushup不止一条 
}

//区间查询 
int querysum(int o,int l,int r,int ql,int qr){
	if(ql<=l && r<=qr) return sumv[o];//要查询的区间完全包含了[l,r] 
	int ans = 0;
	int mid = (l+r)>>1;
	if(ql<=mid) ans += querysum(o<<1,l,mid,ql,qr);
	if(qr>mid) ans += querysum(o<<1|1,mid+1,r,ql,qr);
	return ans;
}

int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	while(m--){
		int opt;
		cin>>opt;
		if(opt == 1){
			int x,y;
			cin>>x>>y;
			change(1,1,n,x,y);
		}
		if(opt == 2){
			int l,r;
			cin>>l>>r;
			cout<<querysum(1,1,n,l,r)<<endl;
		}
	}
}

单点更新,区间查询,维护区间最小值

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6+10;
int n,m,a[N];
int minv[N<<2];

//建树 
void build(int o,int l,int r){
	if(l == r) { //到最后一行了 [1,1] [2,2] ... 
		minv[o] = a[l];
		return;
	}
	int mid = (l+r)>>1; 
	build(o<<1,l,mid);
	build(o<<1|1,mid+1,r);
	pushup(o);//向上合并 
}

void pushup(int o){
	minv[o] = min(minv[o<<1],minv[o<<1|1]);
}



//a[x] += y : change(1,1,n,x,y); 
//单点修改  o为当前到达节点的编号 
void change(int o,int l,int r,int pos,int v){
	if(l == r){
		minv[o] += v;
		return;
	}	
	int mid = (l+r)>>1;
	if(pos <= mid) change(o<<1,l,mid,pos,v);//前半段区间
	else change(o<<1|1,mid+1,r,pos,v); //后半段区间
	pushup(o); //向上更新  有一些线段树维护了多个值,所以pushup不止一条 
}

//区间查询 
int querymin(int o,int l,int r,int ql,int qr){
	if(ql<=l && r<=qr) return minv[o];//要查询的区间完全包含了[l,r] 
	int ans = 1e9+7; //为了求区间最小 初始要设置一个比较大的值 
	int mid = (l+r)>>1;
	if(ql<=mid) ans = min(ans,querymin(o<<1,l,mid,ql,qr));
	if(qr>mid) ans = min(ans,querymin(o<<1|1,mid+1,r,ql,qr));
	return ans;
}


int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	while(m--){
		int opt;
		cin>>opt;
		if(opt == 1){
			int x,y;
			cin>>x>>y;
			change(1,1,n,x,y);
		}
		if(opt == 2){
			int l,r;
			cin>>l>>r;
			cout<<querymin(1,1,n,l,r)<<endl;
		}
	}
}

区间修改,区间查询,标记下放

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6+10;
int n,m,a[N];
int sumv[N<<2],addv[N<<2];

//合并 
void pushup(int o){
	sumv[o] = sumv[o<<1] + sumv[o<<1|1];
}

//建树 
void build(int o,int l,int r){
	if(l == r) { //到最后一行了 [1,1] [2,2] ... 
		sumv[o] = a[l];
		return;
	}
	int mid = (l+r)>>1; 
	build(o<<1,l,mid);
	build(o<<1|1,mid+1,r);
	pushup(o);//向上合并 
}

void puttag(int o,int l,int r,int v){
	addv[o] += v;
	sumv[o] += (r-l+1)*v;
}

void pushdown(int o,int l,int r){
	if(addv[o] == 0) return;
	addv[o<<1] += addv[o];
	addv[o<<1|1] += addv[o];
	int mid = (l+r)>>1;
	sumv[o<<1] += addv[o] * (mid-l+1);
	sumv[o<<1|1] += addv[o] * (r-mid);
	addv[o] = 0;
} 

void optadd(int o,int l,int r,int ql,int qr,int v){
	if(ql<=l&&r<=qr){ //1.完全覆盖(l,r)这个子区间 就先更新好值,打上标记(为后面作标记准备)
		puttag(o,l,r,v); //在puttag这里更新区间的值 打上标记 
		return;
	}
	int mid = (l+r)>>1;
	pushdown(o,l,r);//标记下放 因为接下来要更新子区间了
	if(ql <= mid) optadd(o<<1,l,mid,ql,qr,v);
	if(qr > mid) optadd(o<<1|1,mid+1,r,ql,qr,v);
	pushup(o);
}

int querysum(int o,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr) return sumv[o];
	int ans = 0;
	int mid = (l+r)>>1;
	pushdown(o,l,r);
	if(ql<=mid) ans+=querysum(o<<1,l,mid,ql,qr);
	if(qr>mid) ans+=querysum(o<<1|1,mid+1,r,ql,qr);
	return ans;
}

int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	while(m--){
		int opt;
		cin>>opt;
		if(opt == 1){ //区间加 
			int l,r,v;
			cin>>l>>r>>v;
			optadd(1,1,n,l,r,v);
		}
		if(opt == 2){
			int l,r;
			cin>>l>>r;
			cout<<querysum(1,1,n,l,r)<<endl;
		}
	}
}

线段树2019

单点更新区间查询,维护最小值

#include <iostream>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 110;
int a[maxn];//原数组 
int minv[4 * maxn];//维护最小值

/*
单点更新
区间查询 
*/ 

//维护 
void pushup(int id) {
    minv[id] = min(minv[id << 1], minv[id << 1 | 1]);
}

//建树 
void build(int id, int l, int r) {
    if (l == r) {
        minv[id] = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(id << 1, l, mid);
    build(id << 1 | 1, mid + 1, r);
    pushup(id);
}

//更新 
void update(int id, int l, int r, int x, int v) {
    if (l == r) {
        minv[id] = v;
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid) {
        update(id << 1, l, mid, x, v);
    } else {
        update(id << 1 | 1, mid + 1, r, x, v);
    }
    pushup(id);
}

//查询 
int query(int id,int l,int r,int x,int y){
    if(x <= l && r <= y){
        return minv[id];
    }
    int mid = (l + r) >> 1;
    int ans = inf;
    if( x <= mid){
        ans = min(ans,query(id << 1, l, mid, x,y));
    }
    if( y > mid){
        ans = min(ans,query( id<< 1 | 1,mid + 1,r,x,y));
    }
    return ans;
}

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    build(1, 1, n);
    int q;
    cin >> q;
    for (int i = 0; i < q; ++i) {
        int x, v;
        cin >> x >> v;
        update(1, 1, n, x, v);
    }
    int p;
	cin >> p;
	for (int i = 0; i < p; ++i) {
		int l, r;
		cin >> l >> r;
		cout << query(1, 1, n, l, r) << endl;
	}
    return 0;
}

区间更新,区间查询,维护赋值修改

void up(int p)
{
    if (!p) return;
    s[p] = s[p * 2] + s[p * 2 + 1];
}

void down(int p, int l, int r)
{
    if (col[p])
    {
        int mid = (l + r) / 2;
        s[p * 2] = col[p] * (mid - l + 1);
        s[p * 2 + 1] = col[p] * (r - mid);
        col[p * 2] = col[p * 2 + 1] = col[p];
        col[p] = 0;
    }
}

void modify(int p, int l, int r, int x, int y, int c)
{
    if (x <= l && r <= y)
    {
        s[p] = (r - l + 1) * c;  //仅修改该结点
        col[p] = c;  //增加标记,子结点待修改
        return;
    }
    down(p, l, r);  //下传lazy标记
      int mid = (l + r) / 2;
    if (x <= mid) modify(p * 2, l, mid, x, y, c);
    if (y > mid) modify(p * 2 + 1, mid + 1, r, x, y, c);
    up(p);
}
原文地址:https://www.cnblogs.com/fisherss/p/10920642.html