hdu 4251 劃分樹(板子題)

題意:給定一個數組,求區間中位數,保證給定區間長度是奇數


思路:劃分樹求區間中位數

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX_SIZE 100005  
int sorted[MAX_SIZE];//已經排好序的數據  
int toleft[25][MAX_SIZE];  
int tree[25][MAX_SIZE];  
void build_tree(int left, int right, int deep)   
{  
    int i;  
    if (left == right) return ;  
    int mid = (left + right) >> 1;  
    int same = mid - left + 1; //位於左子樹的數據  
    for (i = left; i <= right; ++i) {//計算放於左子樹中與中位數相等的數字個數  
        if (tree[deep][i] < sorted[mid]) {  
            --same;  
        }  
    }  
    int ls = left;  
    int rs = mid + 1;  
    for (i = left; i <= right; ++i) {  
        int flag = 0;  
        if ((tree[deep][i] < sorted[mid]) || (tree[deep][i] == sorted[mid] && same > 0)) {  
            flag = 1;  
            tree[deep + 1][ls++] = tree[deep][i];  
            if (tree[deep][i] == sorted[mid])  
                same--;  
        } else {  
            tree[deep + 1][rs++] = tree[deep][i];  
        }  
        toleft[deep][i] = toleft[deep][i - 1]+flag;  
    }  
    build_tree(left, mid, deep + 1);  
    build_tree(mid + 1, right, deep + 1);  
}  
int query(int left, int right, int k, int L, int R, int deep)  
{  
    if (left == right)  
        return tree[deep][left];  
    int mid = (L + R) >> 1;  
    int x = toleft[deep][left - 1] - toleft[deep][L - 1];//位於left左邊的放於左子樹中的數字個數  
    int y = toleft[deep][right] - toleft[deep][L - 1];//到right爲止位於左子樹的個數  
    int ry = right - L - y;//到right右邊爲止位於右子樹的數字個數  
    int cnt = y - x;//[left,right]區間內放到左子樹中的個數  
    int rx = left - L - x;//left左邊放在右子樹中的數字個數  
    if (cnt >= k) {  
        //printf("sss %d %d %d\n", xx++, x, y);  
        return query(L + x, L + y - 1, k, L, mid, deep + 1);
        // 因爲x不在區間內 所以沒關係 所以先除去,從L+x開始,然後確定範圍
    }  
    else {  
        //printf("qqq %d %d %d\n", xx++, x, y);  
        return query(mid + rx + 1, mid + 1 + ry, k - cnt, mid + 1, R, deep + 1); 
        //同理 把不在區間內的 分到右子樹的元素數目排除,確定範圍 
    }  
}  
int main()  
{  
    int m, n;  
    int a, b, k;  
    int i,cas=1;  
    while (scanf("%d",&n) !=EOF ) {  
        for (i = 1; i <= n; ++i) {  
            scanf("%d", &sorted[i]);  
            tree[0][i] = sorted[i];  
        }  
        sort(sorted + 1, sorted + 1 + n);  
        build_tree(1, n, 0);  
        scanf("%d",&m);
        printf("Case %d:\n",cas++ );
        for (i = 0; i < m; ++i) {  
            scanf("%d%d", &a, &b);  
            printf("%d\n", query(a, b, (b-a)/2+1, 1, n, 0));  
        }  
    }  
    return 0;  
}  



發佈了60 篇原創文章 · 獲贊 4 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章