链接:点击打开链接
题意:求给定区间中第k小的数
代码:
#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 t,n,m,i,a,b,c; //http://blog.csdn.net/stay_accept/article/details/50492052 scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); 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); while(m--){ scanf("%d%d%d",&a,&b,&c); printf("%d\n",query(a,b,c,1,n,0)); } } return 0; }