链接:点击打开链接
题意:一个长度为N的整数序列,编号0 - N - 1。进行Q次查询,查询编号i至j的所有数中,第K大的数是多少。例如: 1 7 6 3 1。i = 1, j = 3,k = 2,对应的数为7 6 3,第2大的数为6。
代码:
#include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; const int SIZE=100005; int tmp[SIZE],toleft[50][SIZE]; int tree[50][SIZE]; void build(int l,int r,int rt){ int i,mid,sum,lpos,rpos; if(l==r) return; mid=(l+r)>>1; sum=mid-l+1; for(i=l;i<=r;i++) if(tree[rt][i]<tmp[mid]) sum--; lpos=l,rpos=mid+1; for(i=l;i<=r;i++){ if(tree[rt][i]<tmp[mid]) tree[rt+1][lpos++]=tree[rt][i]; else if(tree[rt][i]==tmp[mid]&&sum>0){ tree[rt+1][lpos++]=tree[rt][i]; sum--; } else tree[rt+1][rpos++]=tree[rt][i]; toleft[rt][i]=toleft[rt][l-1]+lpos-l; } build(l,mid,rt+1); build(mid+1,r,rt+1); } int query(int L,int R,int k,int l,int r,int rt){ int mid,newl,newr,cnt; if(L==R) return tree[rt][L]; mid=(l+r)>>1; cnt=toleft[rt][R]-toleft[rt][L-1]; if(cnt>=k){ newl=l+toleft[rt][L-1]-toleft[rt][l-1]; newr=newl+cnt-1; return query(newl,newr,k,l,mid,rt+1); } else{ newr=R+toleft[rt][r]-toleft[rt][R]; newl=newr-(R-L-cnt); return query(newl,newr,k-cnt,mid+1,r,rt+1); } } //划分树模板 int main(){ //详见poj2104 int n,m,i,a,b,c; //http://blog.csdn.net/stay_accept/article/details/50492052 while(scanf("%d",&n)!=EOF){ // memset(tree,0,sizeof(tree)); for(i=1;i<=n;i++){ scanf("%d",&tree[0][i]); tmp[i]=tree[0][i]; } sort(tmp+1,tmp+n+1); build(1,n,0); scanf("%d",&m); while(m--){ scanf("%d%d%d",&a,&b,&c); printf("%d\n",query(a+1,b+1,(b-a+1)-c+1,1,n,0)); //注意是第k大不是第k个数 } } return 0; }