K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 43988 Accepted: 14569 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.Source
Northeastern Europe 2004, Northern Subregion
有沒有覺得題目很熟悉啊?是不是感覺和poj2761很像啊?不過這道題稍微麻煩一點,區間之間存在包含關系,所以就不能用排序+平衡樹做了。
這道題的正確解法是劃分樹(可用於求區間第k小數,復雜度log(n))。劃分樹是一種基於線段樹的數據結構,基本思想是對於一個區間,將它劃分成兩個區間,左區間的數全部小於等於右區間的數,分別對應左右子樹。構建劃分樹時要記錄到達某個位置時進入左子樹的數的個數num,查詢時就可以通過num確定下一個查詢區間,最後將區間范圍縮小到1,也就找到了答案。(詳見代碼…)
#include#include #include #include #include #include #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define LL long long #define pa pair #define MAXN 100005 using namespace std; int n,m,a[MAXN],val[20][MAXN],num[20][MAXN]; inline int read() { int ret=0,flag=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') flag=-1;ch=getchar();} while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();} return ret*flag; } inline void build(int l,int r,int x) { if (l==r) return; int mid=(l+r)>>1,lsame=mid-l+1,same=0,ln=l,rn=mid+1; F(i,l,r) if (val[x][i]a[mid]) val[x+1][rn++]=val[x][i]; else { if (lsame>=++same) num[x][i]++,val[x+1][ln++]=val[x][i]; else val[x+1][rn++]=val[x][i]; } } build(l,mid,x+1); build(mid+1,r,x+1); } inline int query(int st,int ed,int k,int l,int r,int x) { if (l==r) return val[x][l]; int lx,ly,rx,ry,mid=(l+r)>>1; if (st==l) lx=0,ly=num[x][ed]; else lx=num[x][st-1],ly=num[x][ed]-lx; if (ly>=k) { st=l+lx;ed=st+ly-1; return query(st,ed,k,l,mid,x+1); } else { rx=st-l-lx;ry=ed-st+1-ly; st=mid+1+rx;ed=st+ry-1; return query(st,ed,k-ly,mid+1,r,x+1); } } int main() { n=read();m=read(); F(i,1,n) val[0][i]=a[i]=read(); sort(a+1,a+n+1); build(1,n,0); F(i,1,m) { int x=read(),y=read(),k=read(); printf("%d\n",query(x,y,k,1,n,0)); } }