hdu2665 划分树

来源:互联网 发布:驾校坡道数据 编辑:程序博客网 时间:2024/06/04 19:31

模拟了快排的过程 得到的一棵树就是划分树了

静态查询区间第k大很方便

#include<stdio.h>#include<cstdio>#include<iostream>#include<algorithm>using namespace std;#define maxn 111111int tol[30][maxn],s[30][maxn];int sorted[maxn];void build(int dep,int l,int r){    if(l==r)return ;    int mid=((l+r)>>1);    int lpos=l,rpos=mid+1;    int same=(mid-l+1);    for(int i=l;i<=r;++i)        if(s[dep][i]<sorted[mid]){            same--;        }    for(int i=l;i<=r;++i){        if(s[dep][i] < sorted[mid]) s[dep+1][lpos++] = s[dep][i];        else if(s[dep][i]==sorted[mid]&&same>0){            s[dep+1][lpos++] = s[dep][i] ;            same--;        }        else s[dep+1][rpos++] = s[dep][i];                tol[dep][i]=tol[dep][l-1]+lpos-l;    }    build(dep+1,l,mid);    build(dep+1,mid+1,r);}int query(int dep,int l,int r,int L,int R,int k){    if(l == r)return s[dep][l];    int cnt=tol[dep][r]-tol[dep][l-1];    int mid=((L+R)>>1);    if(cnt>=k){        int newl=L+tol[dep][l-1]-tol[dep][L-1];        int newr=newl+cnt-1;        return query(dep+1,newl,newr,L,mid,k);    }    else{        int newr=r+(tol[dep][R]-tol[dep][r]);        int newl=newr-(r-l+1-cnt)+1;        return query(dep+1,newl,newr,mid+1,R,k-cnt);    }}int main(){    int t;scanf("%d",&t);    while(t--){            int n,m,a,b,k;                memset(tol,0,sizeof tol);        memset(s,0,sizeof s);                scanf("%d%d",&n,&m);               for(int i=1;i<=n;++i){               scanf("%d",&s[0][i]);                 sorted[i]=s[0][i];             }         sort(sorted+1,sorted+1+n);        build(0,1,n);                while(m--){            scanf("%d%d%d",&a,&b,&k);            printf("%d\n",query(0,a,b,1,n,k));        }    }    return 0;}


0 0
原创粉丝点击