• 线段树模板


    线段树就像一句话:

    听过很多道理,却依然过不好这一生。 ε(┬┬﹏┬┬)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+1,M+1,R);
            }
            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
    ",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 sumv[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
    ",_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
    ",_sum,_min,_max);
                }
            }
        }
        return 0;
    }

    未完。。。

    之前一直对刘汝佳的线段树信心不大。是因为刘汝佳的板子没有build操作,以至于初始化的时候,是O(nlogn),现在重新复习一下线段树,找到了含有build操作的板子。

    这下线段树的基本操作就已经差不多了!!!

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int INF = 1000000000;
    const int maxnode = 1<<18;
    
    const int maxn = 100000+10;
    int A[maxn];
    
    int op,qL,qR,p,v; //单点更新,建树操作,A[p] = v;
    
    struct IntervalTree {
        int minv[maxnode];
    
        void build(int o,int L,int R) {
            int M = L + (R-L)/2;
            if(L==R) minv[o] = A[L];
            else {
                build(o*2,L,M);
                build(o*2+1,M+1,R);
                minv[o] = min(minv[o*2],minv[o*2+1]);
            }
        }
    
        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+1,M+1,R);
                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 argc, char const *argv[])
    {
        //freopen("in.txt","r",stdin);
        int n,q;
        scanf("%d%d",&n,&q);
        memset(&tree,0,sizeof(tree));
    
        for (int i = 1; i <= n; ++i)
            scanf("%d",&A[i]);
    
        tree.build(1,1,n);
    
        int k,args[20],original[20];
        char cmd[100];
    
        while(q--) {
            scanf("%s",cmd);
    
            int len = strlen(cmd);
    
            k = 0;args[k] = 0;
    
            for(int i=6; i < len; i++) {
                if(isdigit(cmd[i])) 
                    args[k] = args[k]*10 + cmd[i]-'0';
                else {
                    k++;
                    args[k] = 0;
                }
            }
    
            if(cmd[0]=='q') {
                qL = args[0];
                qR = args[1];
                printf("%d
    ", tree.query(1,1,n));
            }
            else {
                for(int i=0; i < k; i++)
                    original[i] = A[args[i]];
    
                for(int i=0; i < k; i++) {
                    p = args[i];
                    v = A[p] = original[(i+1)%k];
                    tree.update(1,1,n);
                }
            }
    
        }
    
    
        return 0;
    }
  • 相关阅读:
    行转列 && 字段拆分
    sqlserver 生成随机值
    mysql查询增加自增列
    Graphx二度关系
    IDEA创建scala项目
    kibana安装
    二十五、Hadoop学记笔记————Hive复习与深入
    二十六、Hadoop学习笔记————Hadoop Yarn的简介复习
    二十四、Hadoop学记笔记————Spark的架构
    二十三、Hadoop学记笔记————Spark简介与计算模型
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6696569.html
Copyright © 2020-2023  润新知