poj 2104 K-th Number 函數式線段樹

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn= 100010;
//segl segr 存線段樹左右點 , chl chr 存主席樹的左右子樹的k值(即序號下標),s爲區間和
struct node{
    int segl, segr, chl ,chr, s;
}tree[30*maxn];
// root 存儲每一個單鏈起始的位置(k值)
int root[maxn*2], tot, n, m, na[maxn*2], nb[maxn*2], len;
int binary(int x){ //二分離散
    int lef= 1, rig= len, mid;
    while( lef <= rig){
        mid = (lef + rig)>> 1;
        if( na[mid] < x) lef = mid + 1;
        else if( na[mid] > x) rig = mid - 1;
        else return mid;
    }
}
int maketree(int lef, int rig){
    if( lef > rig) return 0;
    int k, mid;
    k = ++tot;
    tree[k].segl = lef;
    tree[k].segr = rig;
    tree[k].s = 0;
    mid = (lef + rig) >> 1;
    if( lef == rig) return k;
    tree[k].chl = maketree(lef, mid);
    tree[k].chr = maketree(mid+1, rig);
    return k;
}
//對於每一個x,都可理解爲形成一棵新樹,通過下標鏈過去
int change(int p, int x, int v){
    int k;
    k = ++tot;
    tree[k].segl = tree[p].segl;
    tree[k].segr = tree[p].segr;
    tree[k].chl = tree[p].chl;
    tree[k].chr = tree[p].chr;
    tree[k].s = tree[p].s + v;
    if( tree[p].segl ==x && x == tree[p].segr) return k;
    int mid = ( tree[p].segl + tree[p].segr) >> 1;
    if( x <= mid) tree[k].chl = change(tree[p].chl, x, v);
    else tree[k].chr = change(tree[p].chr, x, v);
    return k;
}
int quary(int y, int x, int k){
    //cout<<y<<"  "<<x<<"  "<<k<<endl;
    if( tree[y].segl == tree[y].segr ) return tree[y].segl;
    int t = tree[tree[y].chl].s - tree[tree[x].chl].s;
    if( k<= t)return quary(tree[y].chl, tree[x].chl, k);
    else return quary(tree[y].chr, tree[x].chr, k - t);
}
int main(){
	//freopen("1.txt", "r", stdin);
	int i, aa, bb, cc;
    while( scanf("%d%d", &n, &m) != EOF){
        for( i= 1; i<= n; i++){
            scanf("%d", &na[i]);
            nb[i] = na[i];
        }
        sort(na+1, na+ n+1);
        len = unique(na+1, na+(n+1)) - (na+1);
        for( i= 1; i<=n; i++)
            nb[i] = binary(nb[i]);
        tot = 0;
        root[0] = maketree(1, len);
        for( i= 1; i<=n; i++){
            root[i] = change(root[i-1], nb[i], 1);
          //  cout<<i<<"  "<<root[i]<<endl;
        }
        for( i= 0; i<m; i++){
            scanf("%d%d%d", &aa, &bb, &cc);
            printf("%d\n", na[quary(root[bb], root[aa-1], cc)]);
        }
    }
	return 0;
}


 

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