poj 2104 K-th Number(划分树裸题)
K-th NumberTime Limit: 20000MS Memory Limit: 65536KTotal Submissions: 33453 Accepted: 10551Case 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 31 5 2 6 3 7 42 5 34 4 11 7 3
Sample Output
563
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题意:
给你含n个数的数组。然后叫你求i,j。之间的第k大数。
思路:
划分树裸题。又重新写了次。加深了印象。也发现了一些需注意的地方。
详细见代码:
#include<algorithm>#include<iostream>#include<string.h>#include<sstream>#include<stdio.h>#include<math.h>#include<vector>#include<string>#include<queue>#include<set>#include<map>using namespace std;const int INF=0x3f3f3f3f;const int maxn=100010;int seg[20][maxn],lnum[20][maxn],sa[maxn];int n,m;void btree(int L,int R,int d){ int i,ls,rs,lm,mid; if(L==R) return ; mid=(L+R)>>1; ls=L,rs=mid+1; lm=mid-L+1; for(i=L;i<=R;i++) if(seg[d][i]<sa[mid]) lm--; for(i=L;i<=R;i++) { lnum[d][i]=(i==L)?0:lnum[d][i-1]; if(seg[d][i]==sa[mid]) { if(lm>0) { lm--; lnum[d][i]++; seg[d+1][ls++]=seg[d][i]; } else seg[d+1][rs++]=seg[d][i]; } else if(seg[d][i]<sa[mid]) { lnum[d][i]++; seg[d+1][ls++]=seg[d][i]; } else seg[d+1][rs++]=seg[d][i]; } btree(L,mid,d+1); btree(mid+1,R,d+1);}int qu(int L,int R,int l,int r,int d,int k){ int ss,s,bb,b,mid; if(L==R) return seg[d][L]; ss=(l==L)?0:lnum[d][l-1];//[1,l-1]进入左树的个数 s=lnum[d][r]-ss;//[l,r]进入左树的个数 mid=(L+R)>>1; if(s>=k)//在左树中 return qu(L,mid,L+ss,L+ss+s-1,d+1,k);//注意边界。可以确定L+ss-1不为所求所以从L+ss else { bb=l-L-ss;//[1,l-1]进入右树的个数.(l-1)-L+1-ss b=r-l+1-s;//[l,r]进入右树的个数 return qu(mid+1,R,mid+bb+1,mid+bb+b,d+1,k-s); }}void init(){ int i; for(i=1;i<=n;i++) { scanf("%d",&seg[0][i]); sa[i]=seg[0][i]; } sort(sa+1,sa+n+1);//注意排序起点啊。。 btree(1,n,0);//mid+1+bb+b-1}int main(){ int i,j,k; while(~scanf("%d%d",&n,&m)) { init(); while(m--) { scanf("%d%d%d",&i,&j,&k); printf("%d\n",qu(1,n,i,j,0,k)); } } return 0;}