zoukankan      html  css  js  c++  java
  • poj 2104 K-th Number(划分树)

    题目链接:http://poj.org/problem?id=2104

    题目分析:该问题给定一段区间中的值,再给定一段查询区间[ql, qr],需要给出该查询区间中的值在排序后的第K大的值;

    使用划分树即可解决该问题;划分树的建树的复杂度为O(NlogN),查询一个区间的第K大值的复杂度为O(logN);

    代码如下:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAX_N = 100000 + 10;
    int sorted[MAX_N];
    int to_left[20][MAX_N];
    int tree[20][MAX_N];
    
    void Build(int l, int r, int deep)
    {
        if (l == r) return;
        int mid = (l + r) >> 1;
        int lc_same = mid - l + 1;
        int l_pos = l, r_pos = mid + 1;
    
        for (int i = l; i <= r; ++i)
        {
            if (tree[deep][i] < sorted[mid])
                lc_same--;
        }
    
        for (int i = l; i <= r; ++i)
        {
            if (tree[deep][i] < sorted[mid])
                tree[deep + 1][l_pos++] = tree[deep][i];
            else if (tree[deep][i] == sorted[mid] && lc_same > 0)
            {
                lc_same--;
                tree[deep + 1][l_pos++] = tree[deep][i];
            }
            else
                tree[deep + 1][r_pos++] = tree[deep][i];
            to_left[deep][i] = to_left[deep][l - 1] + l_pos - l;
        }
        Build(l, mid, deep + 1);
        Build(mid + 1, r, deep + 1);
    }
    
    
    int Query(int l, int r, int ql, int qr, int deep, int k)
    {
        if (l == r)
            return tree[deep][l];
        int mid = (l + r) >> 1;
        int cnt = to_left[deep][qr] - to_left[deep][ql - 1];
    
        if (cnt >= k)
        {
            int new_ql = l + to_left[deep][ql - 1] - to_left[deep][l - 1];
            int new_qr = new_ql + cnt - 1;
            return Query(l, mid, new_ql, new_qr, deep + 1, k);
        }
        else
        {
            int new_qr = qr + to_left[deep][r] - to_left[deep][qr];
            int new_ql = new_qr - (qr - ql - cnt);
            return Query(mid + 1, r, new_ql, new_qr, deep + 1, k - cnt);
        }
    }
    
    
    int main()
    {
        int n, query_times;
    
        scanf("%d %d", &n, &query_times);
        for (int i = 1; i <= n; ++i)
        {
            scanf("%d", &tree[0][i]);
            sorted[i] = tree[0][i];
        }
    
        sort(sorted + 1, sorted + n + 1);
        Build(1, n, 0);
        for (int i = 0; i < query_times; ++i)
        {
            int ql, qr, k, ans;
    
            scanf("%d %d %d", &ql, &qr, &k);
            ans = Query(1, n, ql, qr, 0, k);
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    威尔逊定理 费马小定理 欧拉定理 扩展欧拉定理
    Prufer编码
    [USACO 08MAR]土地购买 Land Acquisition
    [NOIp2004]虫食算
    [POI2000]病毒

    [NOI导刊] [2010] [提高] 淘汰赛制
    开源的基于云开发的通讯录小程序
    党建答题小程序
    抽奖活动小程序按人头开奖技术分析
  • 原文地址:https://www.cnblogs.com/tallisHe/p/4570560.html
Copyright © 2011-2022 走看看