POJ 2104 K-th Number (劃分樹)

~~~題目鏈接~~~


題目大意:給出n個數,現在要求求出區間中的第k大值


思路:劃分樹模版



#include <cstdio>
#include <algorithm>
#define N  100002
using namespace std;
struct node
{
    int num[N], val[N];
}t[1000];//記錄每層的劃分
int n = 0, m = 0, ans = 0, srt[N];
void build_tree(int l, int r, int cur)
{
    int m = (l+(r-l)/2), mid = 0, left_num = 0;
    int s1 = l, s2 = m+1, c1 = 0, c2 = 0;//s1爲下一層分人左邊數開始存的地方, s2爲分入右邊第開始
    if(l == r) return ;
    mid = srt[m];
    for(int i = l; i<=r; i++) if(t[cur].val[i]<mid) c2++;//共有多少個進入左邊的
    left_num = m-l+1-c2;//爲有多少個值等於mid時可以進左邊的
    for(int i = l; i<=r; i++)//選出左右邊的部分
    {
        if(i == l) t[cur].num[i] = 0;
        else t[cur].num[i] = t[cur].num[i-1];
        if(t[cur].val[i]<mid)//小於進入左邊
        {
            t[cur].num[i]++;
            t[cur+1].val[s1++] = t[cur].val[i];
        }
        else if(t[cur].val[i]==mid && c1<left_num)
        {
            c1++;
            t[cur].num[i]++;
            t[cur+1].val[s1++] = t[cur].val[i];
        }
        else
            t[cur+1].val[s2++] = t[cur].val[i];
    }
    build_tree(l, m, cur+1);
    build_tree(m+1, r, cur+1);
}//ok

void query(int a, int b, int k, int l, int r, int cur)
{
    int m = (l+(r-l)/2);
    if(a == b){ans = t[cur].val[a]; return ;}
    int x = t[cur].num[a-1], y = t[cur].num[b];
    if(a == l) x = 0;
    if(y-x>=k)
        query(l+x, l+y-1, k, l, m, cur+1);//進入左邊進行查詢
    else
    {
        k = k-(y-x);
        int s1 = a-l-x, s2 = (b-a+1)-(y-x);
        if(a == l) s1 = 0;
        query(m+1+s1, m+s2+s1, k, m+1, r, cur+1);//進入右邊進行查詢
    }
}



int main()
{
    int i = 0, a = 0, b = 0, k = 0;
    while(scanf("%d %d", &n, &m) != EOF)
    {
        for(i = 1; i<=n; i++)
        {
            scanf("%d", &t[1].val[i]);
            srt[i] = t[1].val[i];
        }
        sort(srt+1, srt+n+1);
        build_tree(1, n, 1);
        while(m--)
        {
            scanf("%d %d %d", &a, &b, &k);
            query(a, b, k, 1, n, 1);
            printf("%d\n", ans);
        }
    }
    return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章