近几天都在做线段树的题,看到这个题本来想从线段树着手。结果发现这个题用划分树做,看了下资料和别人的博客~
地址:http://shizhixinghuo.diandian.com/post/2012-09-02/40037691896
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=1e5+200; int n,m,sorted[maxn],t[25][maxn],toleft[25][maxn]; void Build(int l,int r,int deep) { if(l==r) return; int mid=(l+r)>>1; int same=mid-l+1; for(int i=l;i<=r;i++) if(t[deep][i]<sorted[mid]) same--; int ls=l,rs=mid+1; for(int i=l;i<=r;i++) { toleft[deep][i]=toleft[deep][i-1]; if(t[deep][i]<sorted[mid]) { t[deep+1][ls++]=t[deep][i]; toleft[deep][i]++; } else if(t[deep][i]==sorted[mid]) { if(same) { t[deep+1][ls++]=t[deep][i]; toleft[deep][i]++; same--; } else t[deep+1][rs++]=t[deep][i]; } else t[deep+1][rs++]=t[deep][i]; } Build(l,mid,deep+1); Build(mid+1,r,deep+1); } int Query(int l,int r,int L,int R,int k,int deep) { if(l==r) return t[deep][l]; int mid=(L+R)>>1; int x=toleft[deep][l-1]-toleft[deep][L-1]; int y=toleft[deep][r]-toleft[deep][L-1]; int ry=r-L-y; int rx=l-L-x; int cnt=y-x; if(cnt>=k) return Query(L+x,L+y-1,L,mid,k,deep+1); else return Query(mid+rx+1,mid+1+ry,mid+1,R,k-cnt,deep+1); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=n;i++) { scanf("%d",&sorted[i]); t[0][i]=sorted[i]; } sort(sorted+1,sorted+n+1); Build(1,n,0); while(m--) { int a,b,k; scanf("%d%d%d",&a,&b,&k); printf("%d\n",Query(a,b,1,n,k,0)); } } return 0; }