RQNOJ 找第k小的数

哎。。最近状态很颓废啊。。。
这道题题目算法地球人都知道,就是线段树+二分判定,但我WA了N次囧。。。
设当前的区间是l,r。。那么设C(x)为用线段树的在l,r中小于x的个数,那么如果当前要第k小的数,
则C(x)=k-1,同时x属于l和r之间,所以C(x+1)=k。。就是找出最大的C(x)为k-1的数。。。
Code:

#include<cstdio>#include<algorithm>#include<iostream>#define rep(i,n) for(int i=0;i<n;i++)using namespace std;const int maxn=10000+10;#define Left t*2,l,l+r>>1#define Right t*2+1,l+r>>1,rint*T[maxn*4],n,m,A[maxn],d;void Build(int t,int l,int r){ int s=r-l; T[t]=new int[s]; memcpy(T[t],A+l,sizeof(int)*s); sort(T[t],T[t]+s); if(s>1)Build(Left),Build(Right);}int get(int*D,int s,int x){ int i,l; for(i=-1,l=d;l;l>>=1) if(i+l<s&&D[i+l]<x) i+=l; return i+1;}int Count(int t,int l,int r,int a,int b,int x){ if(l>=b||r<=a)return 0; if(l>=a&&r<=b)return get(T[t],r-l,x); return Count(Left,a,b,x)+Count(Right,a,b,x);}#define Cal(x) (Count(1,0,n,a,b,x))int Ask(int a,int b,int k){ int i,l; for(i=n,l=d;l;l>>=1) if(i-l>=0&&Cal(A[i-l])>=k) i-=l; return A[i-1];}int main(){ //freopen("in","r",stdin); scanf("%d%d",&n,&m); rep(i,n)scanf("%d",A+i); Build(1,0,n);sort(A,A+n);A[n]=1e6;int l,r,k; d=1;while(d<=n)d<<=1;d>>=1; while(m–) { scanf("%d%d%d",&l,&r,&k);l–; printf("%dn",Ask(l,r,k)); }}

One thought on “RQNOJ 找第k小的数

Leave a Reply to Mato完整版 Cancel reply

Your email address will not be published. Required fields are marked *