题意:给一组数字,多次查询求中位数。
思路:划分树。
#include <iostream> #include <string> #include <cstring> #include <cctype> #include <cstdio> #include <map> #include <algorithm> using namespace std; const int maxn=100005; struct DivideTree { int sorted[maxn],dat[20][maxn]; int toleft[20][maxn]; void build(int c,int L,int R) { int mid=(L+R)/2,lsame=mid+1-L,lp=L,rp=mid+1; for(int i=L; i<mid; ++i) if(sorted[i]<sorted[mid]) lsame--; for(int i=L; i<=R; ++i) { if(i==L)toleft[c][i]=0; else toleft[c][i]=toleft[c][i-1]; if(dat[c][i]<sorted[mid]) { dat[c+1][lp++]=dat[c][i]; toleft[c][i]++; } else if(dat[c][i]>sorted[mid]) dat[c+1][rp++]=dat[c][i]; else { if(lsame) { lsame--; toleft[c][i]++; dat[c+1][lp++]=sorted[mid]; } else dat[c+1][rp++]=sorted[mid]; } } if(L==R) return ; build(c+1,L,mid); build(c+1,mid+1,R); } int query(int c,int L,int R,int ql,int qr,int k) { if(L==R) return dat[c][L]; int mid=(L+R)/2; int la,lb,ra,rb; if(L==ql) la=0; else la=toleft[c][ql-1]; lb=toleft[c][qr]; ra=ql-L-la; rb=qr+1-L-lb; int s=lb-la; if(k<=s) return query(c+1,L,mid,L+la,L+lb-1,k); else return query(c+1,mid+1,R,mid+1+ra,mid+rb,k-s); } }; DivideTree tree; int main() { int n,kase=0; while(scanf("%d",&n)!=EOF) { for(int i=1; i<=n; ++i) { scanf("%d",&tree.dat[0][i]); tree.sorted[i]=tree.dat[0][i]; } sort(tree.sorted+1,tree.sorted+n+1); tree.build(0,1,n); int m; scanf("%d",&m); printf("Case %d:\n",++kase); while(m--) { int a,b; scanf("%d%d",&a,&b); printf("%d\n",tree.query(0,1,n,a,b,(b-a)/2+1)); } } return 0; }