POJ 2104 K-th Number
莫队算法+离散化+树状数组+二分
#include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> using namespace std; const int maxn=100000+10; int n,m; int a[maxn],b[maxn],lsh[maxn],pos[maxn]; struct X { int l,r,k,id; }s[5000+10]; int Ans[5000+10]; int L,R,ans; bool cmp(const X&a, const X&b) { if (pos[a.l] == pos[b.l]) return a.r < b.r; return a.l < b.l; } int c[maxn]; int lowbit(int x) {return x&(-x);} int getsum(int pos) { int res=0; for(int i=pos;i>0;i=i-lowbit(i)) res=res+c[i]; return res; } void update(int pos,int val) { for(int i=pos;i<=n;i=i+lowbit(i)) c[i]=c[i]+val; } int get(int num) { int l=1,r=n; while(l<=r) { int mid=(l+r)/2; if(lsh[mid]>num) r=mid-1; else if(lsh[mid]==num) return mid; else l=mid+1; } } void LSH() { for(int i=1;i<=n;i++) lsh[i]=a[i]; sort(lsh+1,lsh+1+n); for(int i=1;i<=n;i++) b[i]=get(a[i]); } int f(int num) { int l=1,r=n,res; while(l<=r) { int mid=(l+r)/2; if(getsum(mid)>num) r=mid-1; else if(getsum(mid)==num) res=mid,r=mid-1; else l=mid+1; } return res; } int main() { scanf("%d%d",&n,&m); int sz=sqrt(1.0*n); for(int i=1;i<=n;i++){scanf("%d",&a[i]);pos[i]=i/sz;} LSH(); for(int i=1;i<=m;i++) { scanf("%d%d%d",&s[i].l,&s[i].r,&s[i].k); s[i].id=i; } sort(s+1,s+1+m,cmp); for(int i=s[1].l;i<=s[1].r;i++) update(b[i],1); Ans[s[1].id]=lsh[f(s[1].k)]; L=s[1].l; R=s[1].r; for(int i=2;i<=m;i++) { while(L<s[i].l) update(b[L],-1),L++; while(L>s[i].l) L--,update(b[L],1); while(R<s[i].r) R++,update(b[R],1); while(R>s[i].r) update(b[R],-1),R--; Ans[s[i].id]=lsh[f(s[i].k)]; } for(int i=1;i<=m;i++) printf("%d\n",Ans[i]); return 0; }