zoukankan      html  css  js  c++  java
  • poj 2104 Kth Number 划分树

    poj 2104 K-th Number
    //poj 2104 K-th Number
    //划分树
    
    //建树和查找,模板题,具体看代码
    
    #define infile freopen("in.txt", "r", stdin);
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    
    #define N 100005
    
    int ans;
    int level[20][N], sorted[N], l_cnt[20][N];
    
    void build(int l, int r, int loc, int dep)
    {
        if(l == r)
            return;
        int mid = l + (r-l)/2;
        int mid_val = sorted[mid];
    
        int cnt = 0;    //记录小于mid_val的个数
        for(int i = l; i <= r; ++i)
            if(level[dep][i] < mid_val)
                cnt++;
        //这里l_tot是从l开始···equal_cnt记录跟mid_val相等且进入左子树的个数
        int l_tot = l, r_tot = mid+1, equal_cnt = 0;
        for(int i = l; i <= r; ++i)
        {
            if(level[dep][i] < mid_val) //小于mid_val的进入左子树
                level[dep+1][l_tot++] = level[dep][i];
            else if(level[dep][i] == mid_val && mid-l+1-cnt > equal_cnt)
            {   //等于mid_val的且没超过左子树限定个数的时候进入左子树
                equal_cnt++;
                level[dep+1][l_tot++] = level[dep][i];
            }
            else
                level[dep+1][r_tot++] = level[dep][i];
            l_cnt[dep][i] = l_tot - l;//记录进入左子树的个数
        }
        build(l, mid, loc*2, dep+1);
        build(mid+1, r, loc*2+1, dep+1);
    }
    
    void find(int l, int r, int from, int to, int k, int dep)
    {
        if(l == r)
        {
            ans = level[dep][l];
            return;
        }
        int mid = l + (r-l)/2;
        int from_cnt;   //记录当前层中,from以前的数进入左子树的个数
        if(from > 1)    //不包括from
            from_cnt = l_cnt[dep][l+from - 2];
        else
            from_cnt = 0;
        //记录当前层中,to以前的数进入又子树的个数,包括to
        int to_cnt = l_cnt[dep][l+to - 1];
    
    
        //接下去那层就应该保持和这层一样的起点,即from左边的个数不变
        //若下一层到左子树,则要从from以左的进入左子树的个数(from_cnt)开始
        //由于from这个数也到左子树所以下一层应从from_cnt+1开始
        //若下一层到右子树要去掉进入左子树的个数
        if(to_cnt - from_cnt >= k)  //from到to之间进入左子树的个数
            find(l, mid, from_cnt+1, to_cnt, k, dep+1);
        else
            find(mid+1, r, from-from_cnt, to-to_cnt, k-(to_cnt-from_cnt), dep+1);
    }
    
    int main(void)
    {
        //infile
        int n, n_query;
        while(scanf("%d%d", &n, &n_query) != EOF)
        {
            for(int i = 1; i <= n; ++i)
            {
                scanf("%d", &level[1][i]);
                sorted[i] = level[1][i];
            }
            sort(sorted+1, sorted+n+1);
            build(1, n, 1, 1);
            while(n_query--)
            {
                int from, to, k;
                scanf("%d%d%d", &from, &to, &k);
                find(1, n, from, to, k, 1);
                printf("%d\n", ans);
            }
        }
        return 0;
    }

    还不懂的话可以看看这个

    http://www.cnblogs.com/pony1993/archive/2012/07/17/2594544.html

  • 相关阅读:
    football statistics
    频繁模式挖掘 Apriori算法 FP-tree
    回首页---用通用底部栏,不用回退键,且多次点击,刷新首页
    对剪切板的失控异常的处理---多半的时间再处理剪切板的失控---冗余操作
    登陆
    搜狗输入法APP的2个剪切板内容获取入口
    实现对屏幕指定内容的操作
    定时删除clientmqueue
    局部优化与整体效果 新增时间>节省时间 权衡利弊
    实时系统的目标
  • 原文地址:https://www.cnblogs.com/gabo/p/2634343.html
Copyright © 2011-2022 走看看