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

    权值线段树的功能有

    • 查询x在整个区间出现的次数
    • 查询[L,R]的数字出现的次数
    • 所有数中出现次数第k大的数字

    基于线段树和二分的思想

    定义(int tree[maxn];)
    tree[i]表示某段区间数字出现的次数

    一般需要离散化操作

    插入数据

    void update(int l,int r,int rt,int x,int op){//插入op个x
        if(l == r){
            tree[rt] += op;
            return;
        }
        int mid = (l + r) >> 1;
        if(x <= mid)update(lson,x,op);
        else update(rson,x,op);
        pushup(rt);
    }
    

    查询x在整个区间出现的次数

    int find(int l,int r,int rt,int x){//查询x在整个区间出现的次数
        if(l == r)return tree[rt];
        int mid = (l + r) >> 1;
        if(x <= mid)return find(lson,x);
        else return find(rson,x);
    }
    

    查询[L,R]的数字出现的次数

    int find2(int l,int r,int rt,int L,int R){//查询[L,R]的数字出现的次数
        if(L <= l && r <= R)return tree[rt];
        int mid = (l + r) >> 1;
        if(R <= mid)return find2(lson,L,R);
        if(L > mid)return find2(rson,L,R);
        return find2(lson,L,R) + find2(rson,L,R);
    }
    

    查询第k大数

    只需要知道右节点数字出现的次数即可
    权值线段树是查询整个区间的,主席树是对于区间查询第k值的

    int kth(int l,int r,int rt,int k){//所有数中出现次数第k大的数字
        if(l == r)return l;
        int mid = (l + r) >> 1;
        int rs = tree[rs(rt)];//只看右结点即可
        if(k <= rs)return kth(rson,k);//在右边
        else return kth(lson,k - rs);//在左边,变为第k - rs大的数字
    }
    

    模板

    #include <iostream>
    #include <cstdio>
    #define ls(rt) rt<<1
    #define rs(rt) rt<<1|1
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    using namespace std;
    const int maxn = 1e5 + 5;
    int tree[maxn >> 2];//下标是数字,tree[i]某段区间数字出现的次数
    void pushup(int rt){
        tree[rt] = tree[ls(rt)] + tree[rs(rt)];
    }
    void update(int l,int r,int rt,int x,int op){//插入op个x
        if(l == r){
            tree[rt] += op;
            return;
        }
        int mid = (l + r) >> 1;
        if(x <= mid)update(lson,x,op);
        else update(rson,x,op);
        pushup(rt);
    }
    int find(int l,int r,int rt,int x){//查询x在整个区间出现的次数
        if(l == r)return tree[rt];
        int mid = (l + r) >> 1;
        if(x <= mid)return find(lson,x);
        else return find(rson,x);
    }
    int find2(int l,int r,int rt,int L,int R){//查询[L,R]的数字出现的次数
        if(L <= l && r <= R)return tree[rt];
        int mid = (l + r) >> 1;
        if(R <= mid)return find2(lson,L,R);
        if(L > mid)return find2(rson,L,R);
        return find2(lson,L,R) + find2(rson,L,R);
    }
    int kth(int l,int r,int rt,int k){//所有数中出现次数第k大的数字
        if(l == r)return l;
        int mid = (l + r) >> 1;
        int rs = tree[rs(rt)];//只看右结点即可
        if(k <= rs)return kth(rson,k);//在右边
        else return kth(lson,k - rs);//在左边,变为第k - rs大的数字
    }
    // int rank(int l,int r,int rt,int x){//查询x在全局的排名
    
    // }
    // int pre(int l,int r,int rt,int x){//查询前驱,小于等于x的最大
    
    // }
    // int ore(int l,int r,int rt,int x){//查询后继,大于x的最大值
    
    // }
    int n;
    int main(){
        int m;
        cin >> n >> m;
        int x;
        for(int i = 0; i < n; i++){
            scanf("%d",&x);
            update(1,n,1,x,1);
        }
        
        return 0;
    }
    
  • 相关阅读:
    oracle 静默安装
    浅析hybrid模式下地支付宝钱包和微信
    LeetCode96_Unique Binary Search Trees(求1到n这些节点能够组成多少种不同的二叉查找树) Java题解
    hdu 5411 CRB and Puzzle 矩阵高速幂
    Hadoop作业性能指标及參数调优实例 (三)Hadoop作业性能參数调优方法
    实现Android4.4系统设置分页滑动浏览功能
    oracle 数据库中数据导出到excel
    Nginx配置upstream实现负载均衡
    公司须要内部的地图服务,准备自己去开发可是成本太高,如今有没有专门为企业提供GIS地图开发的产品呀?大概价格多少?
    图片在内存中的占用的空间大小
  • 原文地址:https://www.cnblogs.com/Emcikem/p/12175702.html
Copyright © 2011-2022 走看看