HDU 2665

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 ;

}
View Code

 

 

 

你可能感兴趣的:(HDU)