线段树

时间:2019-06-12
本文章向大家介绍线段树,主要包括线段树使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

线段树

#include<cstdio>

const int MAXNC = 10100;

int a[MAXNC], tree[MAXNC << 2];
int x, y, n, m;

void built(int l, int r, int o) {
    if(l == r) {
        tree[o] = a[l];
        return;
    }
    
    int m =(r - l >> 1) + l;
    
    built(l, m, o << 1);
    built(m + 1, r, o << 1 | 1);
    
    tree[o] = tree[o << 1] + tree[o << 1 | 1];
    return; 
}

void update(int l, int r, int o) {
    if(l == r) {
        a[x] = y;
        tree[o] = a[x];
        return;
    }
    
    int m = (r - l >> 1) + l;
    
    if(x <= m) update(l, m, o << 1);
    else update(m + 1, r, o << 1 | 1);
    
    tree[o] = tree[o << 1] + tree[o << 1 | 1]; 
}

int query(int l, int r, int o) {
    int m = (r - l >> 1) + l, ans = 0;
    if(l >= x && r <= y) return tree[o];
    if(m >= x) ans += query(l, m, o << 1);
    if(y > m) ans += query(m + 1, r, o << 1 | 1);
    return ans;
}

int main() {
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    built(1, n, 1); 
    
    for(int i = 1; i <= m; i++) {

        scanf("%d", &x);
        if(x == 1) { // 单点修改 
            scanf("%d %d", &x, &y);  // a[x] = y
            update(1, n, 1);    
        }
        else if(x == 2) {  // 区间查询 
            scanf("%d %d", &x, &y);
            printf("%d\n", query(1, n, 1)); 
        }
    }
    
    return 0;
}

/*
5 5
1 2 3 4 5
2 1 3
2 1 5
1 1 5
2 1 5
2 1 4



*/
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 10000
#define INF 2147000047

int n,m;
int minv[MAX],sumv[MAX];//附加信息

int ql, qr;//查询区间 
//查询[qr, ql]中的最小值
int query_min(int o, int L, int R) {
    int M = (L + R) >> 1, ans = INF;
    if(ql <= L && R <= qr) return minv[o];  //递归出口(当前节点完全在查询区间内)
    if(ql <= M)  ans = min(ans, query_min(o*2, L, M) );//往左走(查询区间在左儿子节点中有元素)
    if(M < qr) ans = min(ans, query_min(o*2+1, M+1, R) );//往右走(同理
    return ans; 
} 
//查询[qr, ql]元素和 
int query_sum(int o, int L, int R) {
    int M = (L + R) >> 1 , ans = 0;
    if(ql <= L && R <= qr) return sumv[o];//出口
    if(ql <= M) ans += query_sum(o*2, L, M); 
    if(qr > M) ans += query_sum(o*2+1, M+1, R);
    return ans;
}

int p,v;//修改A[p] = v
void update(int o, int L, int R) {
    int M = (L + R) >> 1;
    if(L == R) {
        minv[o] = v;
        //....
    }
    else {// L < R
        //先递归更新左子树 或 右子树
        if(p <= M) update(o*2, L, M); else update(o*2+1, M+1, R);
        //然后计算本节点的附加值 
        minv[o] = min(minv[o*2], minv[o*2+1]);
    }
} 

int mian() {
    scanf("%d%d",&n,&m);
    for(p = 1; p <= n; p++) {
        scanf("%d", &v);
        update(1, 1, n);//建树 
    }
    
}


原文地址:https://www.cnblogs.com/tyner/p/11011244.html