zoukankan      html  css  js  c++  java
  • 线段树板子

    单点修改,区间查询

    const int maxn = 500005 * 4;    //线段树范围要开4倍
    struct Tree
    {
        int l, r, sum, maxx;
    };
    Tree node[maxn];        //node[maxn]为线段树处理数组
    int a[maxn];            //a[maxn]为原数组
     
    void PushUp(int i)
    {
        node[i].sum = node[i << 1].sum + node[(i << 1) | 1].sum;   //线段树求和 
        node[i].maxx = max(node[i << 1].maxx, node[(i << 1) | 1].maxx);  // 线段树求最大值 
    }
    //创建一个tree 
    void build(int i, int l, int r)
    {
        node[i].l = l; node[i].r = r;
        if (l == r)
        {
            node[i].maxx = a[l];
            node[i].sum = a[l];
            return;
        }
        int mid = (l + r) >> 1;
        build(i << 1, l, mid);// 建立mid左边的树 i<<1所表示的是 tree 上的所在点 
        build((i << 1) | 1, mid + 1, r); //建立mid右边的树采用递推 
        PushUp(i);
    }
    int getsum(int i, int l, int r)
    {
        if (node[i].l == l&&node[i].r == r) 
            return node[i].sum;
        int mid = (node[i].l + node[i].r) >> 1;
        if (r <= mid) 
        {
           return getsum(i << 1, l, r);
        }
        else if (l > mid) {
           return getsum((i << 1) | 1, l, r);
        }
        else 
        {
        return getsum(i << 1, l, mid) + getsum((i << 1) | 1, mid + 1, r);
        }
    }
    int getmax(int i, int l, int r)
    {
        if (node[i].l == l&&node[i].r == r)
            return node[i].maxx;
        int mid = (node[i].l + node[i].r) >> 1;
        if (r <= mid) 
        {
           return getmax(i << 1, l, r);
        }
        else if (l>mid) 
        {
           return getmax((i << 1) | 1, l, r);
        }
        else 
        {
           return max(getmax(i << 1, l, mid), getmax((i << 1) | 1, mid + 1, r));
        }
    }
    void add(int i, int k, int v)            //当前更新的节点的编号为i(一般是1为初始编号,具体得看建立树时使用的第一个编号是什么)。
    {                                //k为需要更新的点的位置,v为修改的值的大小
        if (node[i].l == k&&node[i].r == k)        //左右端点均和k相等,说明找到了k所在的叶子节点
        {
            node[i].sum += v;
            node[i].maxx += v;
            return;    //找到了叶子节点就不需要在向下寻找了
        }
        int mid = (node[i].l + node[i].r) / 2;
        if (k <= mid) a
        {
           add(i << 1, k, v);
        }
        else 
        {
           add((i << 1) | 1, k, v);
        }
        PushUp(i);
    }

    区间修改,区间查询

    const int N = 100005;
    LL a[N];                    //a[N]储存原数组
    LL  lazy[N << 2];            //lazy用来记录该节点的每个数值应该加多少 
    int n, q;
    struct Tree
    {
        int l, r;
        LL sum;
        int mid()
        {
            return (l + r) >> 1;
        }
    }tree[N<<2];        
     
    void PushUp(int rt)
    {
        tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
    }
     
    void PushDown(int rt,int m)
    {
        if (lazy[rt])
        {
            lazy[rt << 1] += lazy[rt];
            lazy[rt << 1 | 1] += lazy[rt];
            tree[rt << 1].sum += lazy[rt] * (m - (m >> 1));
            tree[rt << 1 | 1].sum += lazy[rt] * (m >> 1);
            lazy[rt] = 0;
        }
    }
     
    void build(int l, int r, int rt)
    {
        tree[rt].l = l;
        tree[rt].r = r;
        lazy[rt] = 0;
        if (l == r)
        {
            tree[rt].sum = a[l];
            return;
        }
        int m = tree[rt].mid();
        build(l, m, (rt << 1));
        build(m + 1, r, (rt << 1 | 1));
        PushUp(rt);
    }
     
    void update(LL c, int l, int r, int rt)
    {
        if (tree[rt].l == l&&tree[rt].r==r)
        { 
            lazy[rt] += c;
            tree[rt].sum += c*(r - l + 1);
            return;
        }
        if (tree[rt].l == tree[rt].r)return;
        int m = tree[rt].mid();
        PushDown(rt, tree[rt].r - tree[rt].l + 1);
        if (r <= m)update(c, l, r, rt << 1);
        else if (l > m)update(c, l, r, rt << 1 | 1);
        else 
        {
            update(c, l, m, rt << 1);
            update(c, m + 1, r, rt << 1 | 1);
        }
        PushUp(rt);
    }
     
    LL Query(int l, int r, int rt)
    {
        if (l == tree[rt].l&&r == tree[rt].r)
        {
            return tree[rt].sum;
        }
        int m = tree[rt].mid();
        PushDown(rt, tree[rt].r - tree[rt].l + 1);
        LL res = 0;
        if (r <= m)res += Query(l, r, rt << 1);
        else if (l > m)res += Query(l, r, rt << 1 | 1);
        else
        {
            res += Query(l, m, rt << 1);
            res += Query(m + 1, r, rt << 1 | 1);
        }
        return res;
    }
  • 相关阅读:
    python的浅拷贝和深拷贝的区别
    listview中添加CheckBox的完美实现
    Content Provider 详解
    listView 结合 ArrayList和HashMap 的应用
    App Widget Provider 应用
    Android学习:SeekBar实现音量调节
    android MenuInflater 用XML文件布局
    android 创建菜单的心得
    Android 文件操作
    Android ImageView 总结【转载】
  • 原文地址:https://www.cnblogs.com/lcsdsg/p/14389468.html
Copyright © 2011-2022 走看看