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

    权值线段树就是一棵线段树,不过存的值不是和或积或最大值一类的,而是这一区间上“数”的个数。

    这里就讲一下动态开点的。

    1,存储

    struct seg_tree{
        int val, lson, rson;//个数、左孩子编号、右孩子编号
    }st[MAX];

     2,加点

    void add(int &x,int l, int r, int v) {
        if (!x) x = ++tot;//动态开点 
        st[x].val++;
        if (l == r) return;
        ll mid = (l + r) >> 1;
        if (mid >= v) add(st[x].lson, l, mid, v); 
        else add(st[x].rson, mid + 1, r, v);
    }

    它有什么功能呢?

    其实它就是一个桶,桶能做的它都能做。

    1,查询v出现的次数(单点查询)

    void ask(int x, int l, int r, int v) {
        if (!x) return 0;
        if (l == r) return st[x].val;
        int mid = (l + r) >> 1;
        if (v <= mid) return ask(st[x].lson, l, mid, v);
        else return ask(st[x].rson, mid + 1, r, v);
    }

    2,查询[l, r]中的数出现的次数

    以下代码是求[i, j]中的数出现的次数

    int ask(int x, int l, int r, int i, int j) {
        if (!x) return 0;
        if (i == l && r == j) {
            return st[x].val;
        }
        int mid = (l + r) >> 1;
        if (j <= mid) return ask(st[x].lson, l, mid, i, j);
        else if (i > mid) return ask(st[x].rson, mid + 1, r, i, j);
        else return ask(st[x].lson, l, mid, i, mid) + ask(st[x].rson, mid + 1, r, mid + 1, j);
    }

    3,查询区间第k大(小)

    int ask(int x, int l, int r, int k) {
        if (l == r) return l;
        int mid = (l + r) >> 1;
        if (k <= st[st[x].lson].val) return ask(st[x].lson, l, mid, k);
        else return ask(st[x].rson, mid + 1, r, k st[st[x].lson].val);
    }

    大概就以上几种用法,相信你都学会啦。

    权值线段树也没什么例题,但它是很多高端数据结构的基础。

  • 相关阅读:
    lab anycast rp
    激光 & 激光器
    管道机器人结构设计及控制系统搭建
    自动开关灯装置
    基于MATLAB步态算法仿真的六足仿生机器人
    蓝牙AT模式
    语音识别LD3320
    蓝牙模块设置
    6红外遥控程序
    62、如何消除碎片文件
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/11992303.html
Copyright © 2011-2022 走看看