常常用的到-线段树模板

#define inf 8000000000
#define ll long long
#define mod 1000000007
using namespace std;

const int maxn = 1000005;//开大小

struct node{
    int l,r;//区间[l,r]
    ll add;//区间的懒惰标记
    ll sum;//区间和
    ll mx; //区间最大值
    ll mn; //区间最小值
}tree[maxn<<2];//开4倍

void pushup(int index){
    tree[index].sum = tree[index<<1].sum+tree[index<<1|1].sum;
    tree[index].mx = max(tree[index<<1].mx,tree[index<<1|1].mx);
    //tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn);
}
void pushdown(int index){
    //说明该区间之前更新过
    //要想更新该区间下面的子区间,就要把上次更新该区间的值向下更新
    if(tree[index].add){

        //替换原来的值
        /*
        tree[index<<1].sum = (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
        tree[index<<1|1].sum = (tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
        tree[index<<1].mx = tree[index].add;
        tree[index<<1|1].mx = tree[index].add;
        tree[index<<1].mn = tree[index].add;
        tree[index<<1|1].mn = tree[index].add;
        tree[index<<1].add = tree[index].add;
        tree[index<<1|1].add = tree[index].add;
        tree[index].add = 0;
        */

        //在原来的值的基础上加上val
        /*
        tree[index<<1].sum += (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
        tree[index<<1|1].sum +=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
        tree[index<<1].mx += tree[index].add;
        tree[index<<1|1].mx += tree[index].add;
        //tree[index<<1].mn += tree[index].add;
        //tree[index<<1|1].mn += tree[index].add;
        tree[index<<1].add += tree[index].add;
        tree[index<<1|1].add += tree[index].add;
        tree[index].add = 0;
        */

    }
}
void build(int l,int r,int index){
    tree[index].l = l;
    tree[index].r = r;
    tree[index].add = 0;//刚开始一定要清0
    if(l == r){
        scanf("%d",&tree[index].sum);
        //tree[index].mn =
        tree[index].mx = tree[index].sum;
        return ;
    }
    int mid = (l+r)>>1;
    build(l,mid,index<<1);
    build(mid+1,r,index<<1|1);
    pushup(index);
}

//区间更新
void updata(int l,int r,int index,int val){
    if(l <= tree[index].l && r >= tree[index].r){

        //把原来的值替换成val,因为该区间有tree[index].r-tree[index].l+1
        //个数,所以区间和 以及 最值为:

        /*
        tree[index].sum = (tree[index].r-tree[index].l+1)*val;
        //tree[index].mn = val;
        tree[index].mx = val;
        tree[index].add = val;//延时标记
        */

        //在原来的值的基础上加上val,因为该区间有tree[index].r-tree[index].l+1
        //个数,所以区间和 以及 最值为:

        /*
        tree[index].sum += (tree[index].r-tree[index].l+1)*val;
        tree[index].mn += val;
        tree[index].mx += val;
        tree[index].add += val;//延时标记
        */

        return ;
    }
    pushdown(index);
    int mid = (tree[index].l+tree[index].r)>>1;
    if(l <= mid){
        updata(l,r,index<<1,val);
    }
    if(r > mid){
        updata(l,r,index<<1|1,val);
    }
    pushup(index);
}

//区间查询
ll query(int l,int r,int index){
    if(l <= tree[index].l && r >= tree[index].r){
        return tree[index].sum;
        return tree[index].mx;
        return tree[index].mn;
    }
    pushdown(index);
    int mid = (tree[index].l+tree[index].r)>>1;
    ll ans = 0;
    ll Max = 0;
    ll Min = inf;
    if(l<=mid){
        ans += query(l,r,index<<1);
        Max = max(query(l,r,index<<1),Max);
        Min = min(query(l,r,index<<1),Min);
    }
    if(r>mid){
        ans += query(l,r,index<<1|1);
        Max = max(query(l,r,index<<1|1),Max);
        Min = min(query(l,r,index<<1|1),Min);
    }
    return ans;
    return Max;
    return Min;
    //三种查询内容
}

猜你喜欢

转载自blog.csdn.net/july_xunle/article/details/81104546
今日推荐