POJ 2104 K-th Number 不高效的线段树写法

区间k大数问题


const int Max_N = 100008  ;

int  A[Max_N] ;
vector<int> data[Max_N<<2] ;

void  make_tree(int L , int R , int root){
      if(L == R){
            data[root].clear() ;
            data[root].push_back(A[L]) ;
            return  ;
      }
      int mid = (L + R) >> 1 ;
      make_tree(L , mid , root<<1) ;
      make_tree(mid+1 , R ,root<<1|1) ;
      data[root].resize(R-L+1) ;
      merge(data[root<<1].begin() , data[root<<1].end() ,
            data[root<<1|1].begin() , data[root<<1|1].end() , data[root].begin()) ;
}

int query(int l , int r  , int x , int L , int R , int root){
    if(r < L || l > R)  return 0 ;
    if(l <= L && R <= r)
         return upper_bound(data[root].begin() , data[root].end() , x) - data[root].begin() ;
    int mid = (L + R) >> 1 ;
    return query(l , r , x , L , mid , root<<1)
         + query(l , r , x , mid+1 , R , root<<1|1) ;
}

int  main(){
          int T , N , i , M , l , r , k  , L , R , mid , ans ;
          cin>>N>>M;
          for(i = 1 ; i <= N ; i++)
               scanf("%d" ,&A[i]) ;
          make_tree(1 , N , 1) ;
          sort(A+1 , A+1+N) ;
          while(M--){
              scanf("%d%d%d" ,&l ,&r ,&k) ;
              L = 1 ;
              R = N ;
              while(L <= R){
                   mid = (L + R) >> 1 ;
                   if(query(l , r , A[mid] , 1 , N , 1) >= k){
                      R = mid - 1 ;
                      ans = A[mid] ;
                   }
                   else
                      L = mid + 1 ;
              }
              printf("%d\n" ,ans) ;
          }
          return 0 ;
}


你可能感兴趣的:(POJ 2104 K-th Number 不高效的线段树写法)