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];
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    POJ 3070 Fibonacci【矩阵连乘】
    hdu 3038 How Many Answers Are Wrong【并查集的简单应用】
    POJ 2236 Wireless Network 【并查集的简单应用 判断是否在同一连通分量】
    POJ 1984 Navigation Nightmare【并查集思路总结】
    POJ 2492 A Bug's Life【并查集的简单应用同类的判断】
    POJ 1703 Find them, Catch them【典型并查集:判断在不同的集合】
    POJ 1456 Supermarket【贪心 + 并查集】
    ZOJ 3261 Connections in Galaxy War【并查集】
    POJ 1984 Navigation Nightmare
    POJ 1988 Cube Stacking【并查集的简单应用 堆木块】
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/7634803.html
Copyright © 2011-2022 走看看