解题方法:线段树 + 归并排序 + 二分枚举
本人比较笨,这道题看了N天,主要花在二分枚举上,虽然AC,至今仍然还不是很清楚二分枚举的原理。
希望牛人路过,指导下。
- #include <stdio.h>
- #include <memory.h>
- const long MAX = 100001 ;
- inline int tMin( int u , int v )
- {
- return ( u > v ? v : u ) ;
- }
- inline int tMax( int u , int v )
- {
- return ( u > v ? u : v ) ;
- }
- struct STREE
- {
- int start ;
- int end ;
- int level ;
- struct STREE *leftc ;
- struct STREE *rightc ;
- void BuildST( int s , int e , int lv ) ;
- int Query( int s , int e , int val ) ;
- }Stree[(MAX << 1) + 100] ;
- STREE *root = &Stree[0] ;
- int pos = 1 ;
- int sortarr[18][MAX] ;
- int gNum[MAX] ;
- void STREE::BuildST( int s, int e, int lv )
- {
- start = s ;
- end = e ;
- level = lv ;
- if ( s == e )
- {
- leftc = rightc = NULL ;
- sortarr[lv][s] = gNum[s] ;
- return ;
- }
- int mid = ( s + e ) >> 1 ;
- leftc = &Stree[pos++] ;
- rightc = &Stree[pos++] ;
- leftc->BuildST( s , mid , lv + 1 ) ;
- rightc->BuildST( mid + 1 , e , lv + 1 ) ;
- int i = s , j = mid + 1 , k = s ;
- while ( i <= mid && j <= e )
- {
- if ( sortarr[lv + 1][i] < sortarr[lv + 1][j] )
- sortarr[lv][k++] = sortarr[lv + 1][i++] ;
- else {
- sortarr[lv][k++] = sortarr[lv + 1][j++] ;
- }
- }
- while ( i <= mid )
- {
- sortarr[lv][k++] = sortarr[lv + 1][i++] ;
- }
- while ( j <= e )
- {
- sortarr[lv][k++] = sortarr[lv + 1][j++] ;
- }
- }
- int STREE::Query( int s, int e, int val )
- {
- int ret , mid , l = s , r = e ;
- if ( s == start && end == e )
- {
- if ( val <= sortarr[level][start] ) return 0 ;
- if ( val > sortarr[level][end] ) return ( end - start + 1 ) ;
- if ( val == sortarr[level][end] ) return ( end - start ) ;
- while ( l <= r )
- {
- mid = l + (( r - l ) >> 1) ;
- if ( val <= sortarr[level][mid] )
- r = mid - 1 ;
- else l = mid + 1 ;
- }
- return l - start ;
- }
- else {
- ret = 0 ;
- mid = start + (( end - start ) >> 1) ;
- if ( mid >= s ) ret += leftc->Query( s, tMin(e,mid), val) ;
- if ( mid + 1 <= e ) ret += rightc->Query( tMax(s,mid+1), e, val) ;
- return ret ;
- }
- }
- int main()
- {
- int n , m , s , e , k , i , l , r , mid ;
- scanf("%d %d", &n, &m) ;
- for ( i = 1 ; i <= n ; i++ )
- {
- scanf("%ld", &gNum[i]);
- }
- root->BuildST( 1 , n , 0 ) ;
- for ( i = 1 ; i <= m ; i++ )
- {
- scanf("%d %d %d", &s, &e, &k) ;
- l = 1 , r = n ;
- while ( l <= r )
- {
- mid = l + ((r - l) >> 1) ;
- int p = root->Query( s, e, sortarr[0][mid] ) ;
- if ( k > p )
- l = mid + 1 ;
- else r = mid - 1 ;
- }
- printf("%d/n", sortarr[0][r] ) ;
- }
- return 0 ;
- }
参考某牛人的代码:http://www.wiskey86.cn/wordpress/?p=24
在此感谢!