poj 2104
给出n个数,询问m次,每次询问在区间[l,r]里的第k大的树。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAX 100007
using namespace std;
struct Tree
{
int l,r,sum;
}tree[3000007];
int cnt = 0;
void build ( int &u , int l , int r )
{
u = ++cnt;
tree[u].sum = 0;
if ( l == r ) return;
int mid = l+r>>1;
build ( tree[u].l , l , mid );
build ( tree[u].r , mid+1 , r );
}
void update ( int p , int &u , int l , int r , int x )
{
u = ++cnt;
tree[u] = tree[p];
tree[u].sum++;
int mid = l+r>>1;
if ( l == r ) return;
if ( x > mid )
update ( tree[p].r , tree[u].r , mid+1 , r , x );
else
update ( tree[p].l , tree[u].l , l , mid , x );
}
int query ( int t1 , int t2 , int l , int r , int k )
{
if ( l == r ) return l;
int mid = l+r>>1;
int left = tree[tree[t2].l].sum - tree[tree[t1].l].sum;
if ( left >= k )
return query ( tree[t1].l , tree[t2].l , l , mid , k );
else
return query ( tree[t1].r , tree[t2].r , mid+1 , r , k-left );
}
int a[MAX],num[MAX],num_cnt,root[MAX],n,m;
int main ( )
{
while ( ~scanf ( "%d%d" , &n , &m ) )
{
cnt = 0;
for ( int i = 1 ; i <= n ; i++ )
{
scanf ( "%d" , &a[i] );
num[i] = a[i];
}
sort ( num+1 , num+n+1 );
num_cnt = unique ( num+1 , num+n+1 )-num-1;
build ( root[0] , 1 , num_cnt );
for ( int i = 1 ; i <= n ; i++ )
{
int x = lower_bound ( num+1 , num+n+1 , a[i] )-num;
update ( root[i-1] , root[i] , 1 , num_cnt , x );
}
for ( int i = 1 ; i <= m ;i++ )
{
int l,r,k;
scanf ( "%d%d%d" , &l , &r , &k );
int x = query ( root[l-1] , root[r] , 1 , num_cnt , k );
printf ( "%d\n" , num[x] );
}
}
return 0;
}