Fork me on GitHub

线段树板子

单点修改,区间查询

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;
}

 

posted @ 2021-02-08 16:46  lcsdsg  阅读(59)  评论(0编辑  收藏  举报
【推荐】 程序员网址大全  |  EF CodeFirst  |  百度地图.NET  |  MyNPOI  |  开源  |  我的皮肤  |  ASP.NET MVC4  |  前端提升   |  LINQ   |  WCF   |  EasyUI  |