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

    推荐博客 :http://www.cnblogs.com/TheRoadToTheGold/p/6254255.html

    一、基本概念

    1、线段树是一棵二叉搜索树,它储存的是一个区间的信息。

    2、每个节点以结构体的方式存储,结构体包含以下几个信息:

         区间左端点、右端点;(这两者必有)

         这个区间要维护的信息(事实际情况而定,数目不等)。

    3、线段树的基本思想:二分

    4、线段树一般结构如图所示:

      

    线段树的基本操作 :

    1 . 节点的结构

    struct node
    {
        int l, r;
        int w, f;
    }tree[eps]
    

     2. 建树

    void build(int l, int r, int k){
        tree[k].l = l;
        tree[k].r = r;
        if (tree[k].l == tree[k].r) {
            scanf("%d", &tree[k].w);
            return;
        }
        int m = (tree[k].l + tree[k].r) / 2;
        build(l, m, 2*k);
        build(m+1, r, 2*k+1);
        tree[k].w = tree[k].l + tree[k].r;
    }
    

     3 . 懒标记下传操作

    void down(int k){
        tree[2*k].f += tree[k].f;
        tree[2*k+1].f += tree[k].f;
        tree[2*k].w += (tree[2*k].r - tree[2*k].l + 1)*tree[k].f;
        tree[2*k+1].w += (tree[2*k+1].r - tree[2*k+1].l + 1)*tree[k].f;
        tree[k].f = 0;
    }
    

     4 .单点查询

    void ask(int k){
        if (tree[k].l == tree[k].r) {
            ans = tree[k].w;
            return;
        }
        if (tree[k].f) down(k);
        int m = (tree[k].l + tree[k].r) >> 1;
        if (x <= m) ask(2*k);
        else ask(2*k+1);
    }
    

     5 . 单点修改

    void add(int k){
        if (tree[k].l == tree[k].r){
            tree[k].w += y;
            return;
        }
        if (tree[k].f) down(k);
        int m = (tree[k].l + tree[k].r) >> 1;
        if (x <= m) add(2*k);
        else add(2*k+1);
        tree[k].w = tree[2*k].w + tree[2*k+1].w;
    }
    

     6 . 区间查询

    void sum(int k){
        if (a >= tree[k].l && b <= tree[k].r){
            ans += tree[k].w;
            return;
        }
        if (tree[k].f) down(k);
        int m = (tree[k].l + tree[k].r) >> 1;
        if (a <= m) sum(2*k);
        if (b > m) sum(2*k+1);
    }
    

     7 . 区间修改

    void change(int k){
        if (a >= tree[k].l && b <= tree[k].r){
            tree[k].w += (tree[k].r - tree[k].l + 1)*x;
            tree[k].f += x;
            return;        
        }
        if (tree[k].f) down(k);
        int m = (tree[k].l + tree[k].r) >> 1;
        if (a <= m) change(2*k);
        if (b > m) change(2*k+1);
        tree[k].w = tree[2*k].w + tree[2*k+1].w;
    }
    

     8 . 区间替换的懒标记下传

    void down(int k, int m){
        lazy[k<<1] = lazy[k<<1|1] = lazy[k];
        sum[k<<1] = (m - (m>>1)) * lazy[k];
        sum[k<<1|1] = (m >> 1) * lazy[k];
        lazy[k] = 0;
    }
    

     9 .区间替换的代码

    void change(int l, int r, int k, int pt){
        if (x <= l && r <= y){
            lazy[k] = pt;
            sum[k] = (r - l + 1) * pt;
            return;
        }
        if (lazy[k]) down(k, r - l + 1);
        int m = (l + r) >> 1;
        if (x <= m) change(lson, pt);
        if (y > m) change(rson, pt);
        sum[k] = sum[k<<1] + sum[k<<1|1];
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    [CF1284E]New Year and Castle Construction
    [BZOJ2178]圆的面积并(格林公式)
    [CF1146H]Satanic Panic(dp)
    [CF1019D]Large Triangle
    [ICPC World Finals 2018][LOJ6409]熊猫保护区(voronoi图)
    [CF gym 101471A][LOJ6470]Airport Construction
    [BZOJ2809]dispatching(左偏树)
    [HDU5784]How Many Triangles
    [CF372E]Drawing circles is fun(反演)
    [NOI2005][BZOJ1502][洛谷P4207]月下柠檬树(自适应Simpson积分)
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/7634803.html
Copyright © 2011-2022 走看看