K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 35704 Accepted: 11396 Case Time Limit: 2000MS
Description
You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment.Input
The first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000).Output
For each question output the answer to it --- the k-th number in sorted a[i...j] segment.Sample Input
7 3 1 5 2 6 3 7 4 2 5 3 4 4 1 1 7 3
Sample Output
5 6 3
Hint
This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed. 題解: 本題要求給定區間的第k小元素,可以用劃分樹,在我的博客poj2104劃分樹解法有劃分樹的解法,至於劃分樹可以參考劃分樹 本題要用到的主席樹相關知識在主席樹讀書筆記可以找到。主席樹的每個節點對應一顆線段樹,每個節點的意義為離散後原序列的某個後綴。在每棵線段樹中若元素出現則標記為1,問題可以轉化為求區間的前k個數,第k個數即為第k小的元素,在區間上操作是線段樹的特色。 貼段代碼:#include#include #include using namespace std; const int MAXN=100000+100; const int MAXM=MAXN*20; int tot,n,m; int da[MAXN],sDa[MAXN]; int leftChild[MAXM],rightChild[MAXM],wei[MAXM],chairTNode[MAXM]; /********************************** *參數:待處理元素區間 *功能:建立一棵空線段樹 *返回值:返回根節點下標 ***********************************/ int Build(int left,int right) { int id=tot++; wei[id]=0; if(left >1; leftChild[id]=Build(left,mid); rightChild[id]=Build(mid+1,right); } return id; } int Update(int root,int pos,int val) { int l=1,r=m,mid,newRoot=tot++,retRoot=newRoot; wei[newRoot]=wei[root]+val; while(l >1; if(pos<=mid) { //確定節點孩子節點 leftChild[newRoot]=tot++; rightChild[newRoot]=rightChild[root]; //確定待跟新節點以及歷史版本 newRoot=leftChild[newRoot]; root=leftChild[root]; r=mid; } else { rightChild[newRoot]=tot++; leftChild[newRoot]=leftChild[root]; newRoot=rightChild[newRoot]; root=rightChild[root]; l=mid+1; } wei[newRoot]=wei[root]+val; } return retRoot; } int Query(int leftRoot,int rightRoot,int k) { int l=1,r=m,mid; while(l >1; if(wei[leftChild[leftRoot]]-wei[leftChild[rightRoot]]>=k)//第k小值在左子樹 { //確定查找新區間 leftRoot=leftChild[leftRoot]; rightRoot=leftChild[rightRoot]; r=mid; } else { k-=wei[leftChild[leftRoot]]-wei[leftChild[rightRoot]]; leftRoot=rightChild[leftRoot]; rightRoot=rightChild[rightRoot]; l=mid+1; } } return l; } int main() { int q,i; int ql,qr,k; while(scanf("%d%d",&n,&q)!=EOF) { m=0; tot=0; for(i=1;i<=n;i++) { scanf("%d",&da[i]); sDa[i]=da[i]; } sort(sDa+1,sDa+n+1); m=unique(sDa+1,sDa+1+n)-sDa-1; chairTNode[n+1]=Build(1,m); //cout<<"**********"< =1;i--) { int pos=lower_bound(sDa+1,sDa+1+m,da[i])-sDa; chairTNode[i]=Update(chairTNode[i+1],pos,1); } while(q--) { scanf("%d%d%d",&ql,&qr,&k); printf("%d\n",sDa[Query(chairTNode[ql],chairTNode[qr+1],k)]); } } system("pause"); return 0; }