http://acm.hdu.edu.cn/showproblem.php?pid=2665
在线询问静态区间k大
去学主席树,没看懂;学树套树,没看懂;最后划分树拯救了我,orz......
划分树讲解看百度百科
#include <iostream> #include <algorithm> using namespace std ; int tree[30][100005] ; int toleft[30][100005] ; int sorted[100005] ; void build(int l,int r,int dep) { if(l==r)return ; int m=(l+r)>>1 ; int same=m-l+1 ; for(int i=l ;i<=r ;i++) if(tree[dep][i]<sorted[m]) same-- ; int ll=l ; int rr=m+1 ; for(int i=l ;i<=r ;i++) { if(tree[dep][i]<sorted[m]) tree[dep+1][ll++]=tree[dep][i] ; else if(tree[dep][i]==sorted[m] && same>0) { tree[dep+1][ll++]=tree[dep][i] ; same-- ; } else tree[dep+1][rr++]=tree[dep][i] ; toleft[dep][i]=toleft[dep][l-1]+ll-l ; } build(l,m,dep+1) ; build(m+1,r,dep+1) ; } int query(int L,int R,int k,int l,int r,int dep) { if(L==R)return tree[dep][L] ; int m=(l+r)>>1 ; int cnt=toleft[dep][R]-toleft[dep][L-1] ; if(cnt>=k) { int ll=l+toleft[dep][L-1]-toleft[dep][l-1] ; int rr=ll+cnt-1 ; return query(ll,rr,k,l,m,dep+1) ; } else { int rr=R+toleft[dep][r]-toleft[dep][R] ; int ll=rr-(R-L-cnt) ; return query(ll,rr,k-cnt,m+1,r,dep+1) ; } } int main() { int t ; scanf("%d",&t) ; while(t--) { int n,m ; scanf("%d%d",&n,&m) ; for(int i=1 ;i<=n ;i++) { scanf("%d",&tree[0][i]) ; sorted[i]=tree[0][i] ; } sort(sorted+1,sorted+1+n) ; build(1,n,0) ; while(m--) { int a,b,k ; scanf("%d%d%d",&a,&b,&k) ; printf("%d\n",query(a,b,k,1,n,0)) ; } } return 0 ; }