zoukankan      html  css  js  c++  java
  • 划分树

    推荐博客 : https://www.cnblogs.com/hchlqlz-oj-mrj/p/5744308.html

      划分树,类似于线段树,是一个完全二叉树,主要可以用来求解区间第K大元素,时间复杂度为 logn, 快排也可以实现这个操作,但是会改变原序列,就需要每次操作后在复原。

    下面给出一棵划分树的建树图:

    红色标记的点都进入了左区间。

    划分树有两个重要的数组 , val[20][i] , 表示在第 k 层所有元素的分布情况,第 0 层表示初始序列。

    num[20][i] 表示第 k 层第 i 个元素前由多少个元素进了区间的左侧,包括该元素本身。

    建树的过程类似线段树

    void build(int l, int r, int k){
        if (l == r) return;
        int mid = (l+r)>>1;
        int isame = mid-l+1;
        
        for(int i = l; i <= r; i++) {
            if (val[k][i] < sorted[mid]) isame--; // 有多少个同中间值相同的元素被放入左侧。
        }
        int ls = l, rs = mid+1;
        for(int i = l; i <= r; i++){
            if (i == l) num[k][i] = 0;
            else num[k][i] = num[k][i-1];
            
            if (val[k][i] < sorted[mid] || (isame > 0 && val[k][i] == sorted[mid])) {
                val[k+1][ls++] = val[k][i];
                num[k][i]++;
                if (val[k][i] == sorted[mid]) isame--;
            }
            else val[k+1][rs++] = val[k][i];
        }
        build(l, mid, k+1);
        build(mid+1, r, k+1);
    }
    

     查询的过程

    int ans = 0;
    void query(int l, int r, int k, int ls, int rs, int kk){
        //printf("ls = %d r = %d
    ", ls, rs);
        if (l == r) {ans = val[k][l]; return;}
        
        int ly;
        if (ls == l) ly = 0;
        else ly = num[k][ls-1]; // 区间左侧进入左区间的个数 
        int lsum = num[k][rs]-ly; // 整个区间进入左区间的个数
        int mid = (l+r) >> 1;
        if (kk <= lsum){
            int lt = l+ly;
            query(l, mid, k+1, lt, l+ly+lsum-1, kk);
        } 
        else{
            int rt = mid+1+ls-l-ly;
            query(mid+1, r, k+1, rt, rt+rs-ls+1-lsum-1, kk-lsum);
        }
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    HTML基础
    Java基础05-计算机单位
    Java基础04-运算符
    Java基础03-数据类型
    Java基础02-变量
    Java基础01-HelloWorld
    MarkDown基本使用
    短视频学习
    c# as 总结
    在C#中使用Nullable类型和 tuple类
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8696551.html
Copyright © 2011-2022 走看看