线段树模板

Posted 树的种子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树模板相关的知识,希望对你有一定的参考价值。

线段树就像一句话:

听过很多道理,却依然过不好这一生。 ε(┬┬﹏┬┬)3

 

还是总结一下线段树的知识点。网上有很多模板,其中最突出的就不用说了,《线段树完全版》主要是没怎么学,没怎么去了解那个大佬的风格。

这里我记录一下刘汝佳大牛的板子。

 

#include <bits/stdc++.h>

using namespace std;

const int maxnode = 1<<17;// maxnode = 2<<n - 1;
const int INF = 0x3f3f3f3f;


//点修改
int ql,qr; //查询
int p,v;    //A[p] = v;
struct IntervalTree {
    int minv[maxnode];

    void update(int o,int L,int R) {
        int M = L + (R-L)/2;
        if(L==R) minv[o] = v;
        else {
            if(p<=M) update(o*2,L,M);
            else update(o*2,L,M);
        }
        minv[o] = min(minv[o*2],minv[o*2+1]);
    }

    int query(int o,int L,int R) {
        int M = L + (R-L)/2,ans = INF;
        if(ql<=L&&R<=qr) return minv[o];
        if(ql<=M) ans = min(ans,query(o*2,L,M));
        if(M<qr) ans = min(ans,query(o*2+1,M+1,R));
        return ans;
    }

};

IntervalTree tree;

int main()
{
    int n,m;
    int op;
    while(scanf("%d%d",&n,&m)==2) {
        memset(&tree,0,sizeof(tree));
        while(m--) {
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d%d",&p,&v);
                tree.update(1,1,n);
            }
            else {
                scanf("%d%d",&ql,&qr);
                printf("%d\n",tree.query(1,1,n));
            }
        }
    }
    return 0;
}

 

 

#include <bits/stdc++.h>

using namespace std;

//区间修改
// add(l,r,v)
const int maxnode = 1<<17;// maxnode = 2<<n - 1;
const int INF = 0x3f3f3f3f;

int _min,_max,_sum;

struct IntervalTree {
    
    int sum[maxnode],minv[maxnode],maxv[maxnode],addv[maxnode];
    
    void maintain(int o,int L,int R) {
        int lc = o*2,rc=o*2+1;
        sumv[o] = minv[o] = maxv[o] = 0;
        if(R>L) {
            sumv[o] = sumv[lc] + sumv[rc];
            minv[o] = min(minv[lc],minv[rc]);
            maxv[o] = max(maxv[lc],maxv[rc]);
        }
        minv[o] +=addv[o];
        maxv[o] +=addv[o];
        sumv[o] +=addv[o]*(R-L+1);
    }
    
    void update(int o,int L,int R) {
        int lc = o*2,rc = o*2+1;
        if(ql<=L&&qr>=R)
            addv[o]+=v;
        else {
            int M = L + (R-L)/2;
            if(ql<=M) update(lc,L,M);
            if(qr>M) update(rc,M+1,R);
        }
        maintain(o,L,R);
    }
    
    void query(int o,int L,int R,int add) {
        if(ql<=L&&qr>=R) {
            _sum +=sumv[o] + add*(R-L+1);
            _min = min(_min,minv[o]+add);
            _max = max(_max,maxv[o]+add);
        }
        else {
            int M = L + (R-L)/2;
            if(ql<=M) query(o*2,L,M,add+addv[o]);
            if(qr>M) query(o*2+1,M+1,add+addv[o]);
        }
    }
    
};

IntervalTree tree;

int main()
{
    int n,m,op;
    while(scanf("%d%d",&n,&m)==2) {
        memset(&tree,0,sizeof(tree));
        scanf("%d%d%d",&op,&ql,&qr);
        if(op==1)
        {
            scanf("%d",&v);
            tree.update(1,1,n);
        }
        else {
            _sum = 0;_min=INF;_max = -INF;
            tree.query(1,1,n,0);
            printf("%d %d %d\n",_sum,_min,_max);
        }
    }
    return 0;
}

 

 

 

#include <bits/stdc++.h>

using namespace std;

const int maxnode = 1<<17;// maxnode = 2<<n - 1;
const int INF = 0x3f3f3f3f;

int _min,_max,_sum;

//区间修改
// set(l,r,v) A[l...r] = v;
struct IntervalTree {
    
    int sumv[maxnode],minv[maxnode],maxv[maxnode],setv[maxnode];
    
    //维护信息
    void maintain(int o,int L,int R) {
        int lc = o*2,rc = o*2 + 1;
        if(R>L) {
            sumv[o] = sumv[lc] + sumv[rc];
            minv[o] = min(minv[lc],minv[rc]);
            maxv[o] = max(maxv[lc],maxv[rc]);
        }
        if(setv[o]>=0) {
            minv[o] = maxv[o] = setv[o];
            sumv[o] = setv[o]*(R-L+1);
        }
    }
    
    //标记传递
    void pushdown(int o) {
        int lc = o*2,rc = o*2 + 1;
        if(setv[o]>=0)
        {
            setv[lc] = setv[rc] = setv[o];
            setv[o] = -1;
        }
    }
    
    void update(int o,int L,int R) {
        int lc = o*2,rc = o*2+1;
        if(ql<=L&&qr>=R) {
            setv[o] = v;
        }
        else {
            pushdown(o);
            int M = L + (R-L)/2;
            if(ql<=M) {
                update(lc,L,M);
            }
            else maintain(lc,L,M);
            if(qr>M) {
                update(rc,M+1,R);
            }
            else maintain(rc,M+1,R);
        }
        maintain(o,L,R);
    }
    
    void query(int o,int L,int R) {
        if(setv[o]>=o) {
            _sum +=setv[o]*(min(R,qr)-max(L,ql)+1);
            _min = min(_min,setv[o]);
            _max = max(_max,setv[o]);
        }
        else if(ql<=L&&qr>=R) {
            _sum +=sumv[o];
            _min = min(_min,minv[o]);
            _max = max(_max,maxv[o]);
        }
        else {
            int M = L + (R-L)/2;
            if(ql<=M) query(o*2,L,M);
            if(qr>M) query(o*2+1,M+1,R);
        }
    }
    
};


IntervalTree tree;

int main()
{
    int n,m,op;
    while(scanf("%d%d",&n,&m)==2) {
        memset(&tree,0,sizeof(tree));
        memset(tree.setv,-1,sizeof(tree.setv));
        tree.setv[1] = 0;
        while(m--) {
            scanf("%d%d%d",&op,&ql,&qr);
            if(op==1) {
                scanf("%d",&v);
                tree.update(1,1,n);
            }
            else {
                _sum = 0,_min = INF;_max = -INF;
                tree.query(1,1,n);
                printf("%d %d %d\n",_sum,_min,_max);
            }
        }
    }
    return 0;
}

 

未完。。。

以上是关于线段树模板的主要内容,如果未能解决你的问题,请参考以下文章

线段树模板整理

线段树模板总结

线段树模板

模板线段树-单点修改,区间查询

P3834 模板可持久化线段树 1(主席树)

模板 线段树(部分功能)