程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu2665-Kth number

hdu2665-Kth number

編輯:C++入門知識

Kth number

Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4585 Accepted Submission(s): 1461


Problem Description Give you a sequence and ask you the kth big number of a inteval.
Input The first line is the number of the test cases.
For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere.
The second line contains n integers, describe the sequence.
Each of following m lines contains three integers s, t, k.
[s, t] indicates the interval and k indicates the kth big number in interval [s, t]
Output For each test case, output m lines. Each line contains the kth big number.
Sample Input
1 
10 1 
1 4 2 3 5 6 7 8 9 0 
1 3 2 

Sample Output
2

Source HDU男生專場公開賽——趕在女生之前先過節(From WHU)
Recommend zty | We have carefully selected several similar problems for you: 2660 2662 2667 2663 2661

一開始用歸並樹 超時了, 只好去學劃分樹= = 媽蛋,看了好久才理解。

劃分樹建樹的原理和歸並樹有點類似,只不過劃分樹采用的是快速排序的方式,先把原數列排序,建樹的時候以中間大的數為基數,將小的扔左邊,大的扔右邊,有一些小細節,如有多個數與基數相同的時候,需要一個臨時變量記錄一下,用seg[dep][i] 記錄i到左邊區間有 多少個數是小於基數的,查詢的時候,判斷區間 還有就

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 100000+10;

struct node{
    int lson,rson;
    int mid(){
        return (lson+rson)>>1;
    }
}tree[maxn*4];

int seg[25][maxn];
int lftnum[25][maxn];
int num[maxn];
int n,m,sta,ed;

void build(int L,int R,int rt,int dep){
    tree[rt].lson = L;
    tree[rt].rson = R;
    if(L==R) return;
    int mid = tree[rt].mid(),key = num[mid],scnt = mid-L+1;//左邊中間值的個數
    for(int i = L; i <= R ; i++){
        if(seg[dep][i] < num[mid]){
            scnt--;
        }
    }
    int lp = L,rp = mid+1;
    for(int i = L; i <= R; i++){
        if(i==L){
            lftnum[dep][i] = 0;
        }else{
            lftnum[dep][i] = lftnum[dep][i-1];
        }
        if(seg[dep][i] < key){
            lftnum[dep][i]++;
            seg[dep+1][lp++] = seg[dep][i];
        }
        else if(seg[dep][i] > key){
            seg[dep+1][rp++] = seg[dep][i];
        }
        else{
            if(scnt>0){
                scnt--;
                lftnum[dep][i]++;
                seg[dep+1][lp++] = seg[dep][i];
            }else{
                seg[dep+1][rp++] = seg[dep][i];
            }
        }
    }
    build(L,mid,rt<<1,dep+1);
    build(mid+1,R,rt<<1|1,dep+1);
}
int query(int L,int R,int rt,int dep,int k){
    if(tree[rt].lson==tree[rt].rson){
        return seg[dep][L];
    }
    int cnt,act;
    if(L==tree[rt].lson){
        cnt = lftnum[dep][R];
        act = 0;
    }else{
        cnt = lftnum[dep][R] - lftnum[dep][L-1];
        act = lftnum[dep][L-1];
    }
    int mid = tree[rt].mid();
    if(cnt >= k){
        L = tree[rt].lson + act;
        R = tree[rt].lson + act + cnt-1;
        return query(L,R,rt<<1,dep+1,k);
    }else{
        int a = L-tree[rt].lson-act;
        int b = R-L-cnt+1;
        L = mid + a + 1;
        R = mid + a + b;
        return query(L,R,rt<<1|1,dep+1,k-cnt);
    }

}
int main(){
    int ncase;
    cin >> ncase;
    while(ncase--){
        cin >> n >> m;
        for(int i = 1; i <= n; i++){
            scanf("%d",&num[i]);
            seg[0][i] = num[i];
        }
        sort(num+1,num+n+1);
        build(1,n,1,0);
        while(m--){
            int k;
            scanf("%d%d%d",&sta,&ed,&k);
            printf("%d\n",query(sta,ed,1,0,k));
        }
    }
    return 0;
}


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved