題目
問題描述
給定乙個序列,每次詢問序列中第l個數到第r個數中第k大的數是哪個。
輸入格式
第一行包含乙個數n,表示序列長度。
第二行包含n個正整數,表示給定的序列。
第三個包含乙個正整數m,表示詢問個數。
接下來m行,每行三個數l,r,k,表示詢問序列從左往右第l個數到第r個數中,從大往小第k大的數是哪個。序列元素從1開始標號。
輸出格式
總共輸出m行,每行乙個數,表示詢問的答案。
樣例輸入
51 2 3 4 5
21 5 2
2 3 2
樣例輸出42
資料規模與約定
對於30%的資料,n,m<=100;
對於100%的資料,n,m<=1000;
保證k<=(r-l+1),序列中的數<=106。
題解
快排的原理:利用快速排序將無序序列轉換為有序序列的過程中,經過多次的劃分;(這裡假定進行降序排列)在每一次的劃分中,在序列中找到乙個樞軸(pivot),劃分的結果是 pivot 左邊的數均比它大,右邊的數均比它小;然後對子序列進行同樣的操作,遞迴進行、直到所有子串行有序為止。
改造:我們的目標是找到第k大的數,若在一次劃分之後、pivot左邊的數(加上它本身)共有k個,那麼pivot位置上的數就是我們要找的第k大的數;其一:我們不必要求前k-1大的數有序,所以不必繼續進行遞迴劃分;其二:每一次的劃分都將原序列分為左、右兩個子串行,快排演算法需要對這兩個子串行都繼續進行遞迴的劃分,而在這裡我們只需要根據情況(具體看演算法步驟)選擇乙個子串行繼續劃分即可;因此這種求第k大的數演算法的時間複雜度小於快速排序的複雜度,為o(n*logk)
演算法步驟:經過一次劃分(partition)之後,樞軸pivot將原序列劃分為兩個部分:s和t [即原序列變為(s t)、pivot包含在子串行s中、注意使用降序排序],會出現下列三種情況:
1.子串行s中有k個數,此時pivot位置即為第k大的數,演算法結束
2.子串行s中的數字個數小於k,假設個數為l,則需要子串行t中繼續遞迴劃分出來前(k-l)個數
3.子串行s中的數字個數大於k,則需要子串行s中繼續遞迴劃分出來前k個數
**:
#include
#include
#include
#include
using
namespace std;
/*快速排序的一次劃分*/
intpartition
(int a,
int low,
int high)
a[i]
= a[j]
;while
(i>=x)
a[j]
= a[i];}
a[i]
= x;
return i;
}/* 降序排序,當一次劃分之後、pivot左邊的數(包括它本身)恰為k個時,停止劃分*/
void
find_kmax
(int a,
int low,
int high,
int k)
else
if(len > k)}}
intmain()
;int len =
sizeof
(arr)
/sizeof
(int);
// 求陣列長度
int l, r, k;
// 區間為[l, r],從1開始
scanf
("%d %d %d"
,&l,
&r,&k)
;int a[
100]
;memcpy
(a, arr,
sizeof
(arr));
// 將arr陣列的元素copy到a陣列中,這麼做是為了避免破壞原陣列、能夠進行多次不同區間的查詢
find_kmax
(a, l-
1, r-
1, k)
;// 注意區間下標與陣列下標的轉換
printf
("%d\n"
, a[l-
1+ k-1]
);// 注意第k大的數在陣列a中的位置!
return0;
}
題解二:學了快速排序後的另外一種解法:
#include
#include
using namespace std;
const
int n=
1e6+10;
int n,k,q[n]
;void
quick_sort
(int q,
int l,
int r)
quick_sort
(q,l,j)
;quick_sort
(q,j+
1,r);}
intmain()
}return0;
}
區間K大數查詢
問題描述 給定乙個序列,每次詢問序列中第l個數到第r個數中第k大的數是哪個。輸入格式 第一行包含乙個數n,表示序列長度。第二行包含n個正整數,表示給定的序列。第三個包含乙個正整數m,表示詢問個數。接下來m行,每行三個數l,r,k,表示詢問序列從左往右第l個數到第r個數中,從大往小第k大的數是哪個。序...
區間k大數查詢
問題描述 給定乙個序列,每次詢問序列中第l個數到第r個數中第k大的數是哪個。輸入格式 第一行包含乙個數n,表示序列長度。第二行包含n個正整數,表示給定的序列。第三個包含乙個正整數m,表示詢問個數。接下來m行,每行三個數l,r,k,表示詢問序列從左往右第l個數到第r個數中,從大往小第k大的數是哪個。序...
區間k大數查詢
問題描述 給定乙個序列,每次詢問序列中第 l個數到第 r個數中第 k大的數是哪個。輸入格式 第一行包含乙個數 n,表示序列長度。第二行包含 n個正整數,表示給定的序列。第三個包含乙個正整數 m,表示詢問個數。接下來m行,每行三個數 l,r,k 表示詢問序列從左往右第 l個數到第 r個數中,從大往小第...