码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 2665 Kth number(划分树)

时间:2015-08-16 07:03:07      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:

题意:给定一列数,每次查询区间[s,t]中的第k大;

参考:http://www.cnblogs.com/kane0526/archive/2013/04/20/3033212.html

      http://www.cnblogs.com/kuangbin/archive/2012/08/14/2638829.html

思路:快排思想+线段树=划分树,也就是树的每一层都按规则划分;

        对于本题,建树前,保存原数列排序后的数列,原数列作为树的顶层;

        建树时,考虑当前区间中的中间值,若大于中间值,在下一层中放右边,否则放左边,实现划分;

        维护每层中1到i中小于区间中间数的个数(区间左边的数),方便查询时计算;

        查询时,比较待查询区间与当前区间中左边数的个数,以便查询子区间;

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int tree[30][100010];
int as[100010];
int toleft[30][100010];
void build(int l,int r,int dep)
{
    if(l==r)return;
    int mid=(l+r)/2;
    int same=mid-l+1;//表示等于中间值而且被分入左边的个数
    for(int i=l;i<=r;i++)
      if(tree[dep][i]<as[mid])
         same--;   //目的是标记在左边的数
    int lpos=l;
    int rpos=mid+1;
    for(int i=l;i<=r;i++)
    {
        if(tree[dep][i]<as[mid])//比中间的数小,分入左边
             tree[dep+1][lpos++]=tree[dep][i];
        else if(tree[dep][i]==as[mid]&&same>0)//相等,放左边
        {
            tree[dep+1][lpos++]=tree[dep][i];
            same--;
        }
        else  //比中间值大分入右边
            tree[dep+1][rpos++]=tree[dep][i];
        toleft[dep][i]=toleft[dep][l-1]+lpos-l;//从1到i放左边的个数

    }
    build(l,mid,dep+1);
    build(mid+1,r,dep+1);

}
int query(int L,int R,int l,int r,int pos,int k){
   if(l==r) return tree[pos][l];
   int mid=(L+R)/2; //注意
   int cnt=toleft[pos][r]-toleft[pos][l-1]; //待查询区间中左边的数的个数
   if(cnt>=k){         //不够,扩大区间
      int newl=L+toleft[pos][l-1]-toleft[pos][L-1]; //查询区间向左移
      int newr=newl+cnt-1;
      return query(L,mid,newl,newr,pos+1,k);
   }
   else{  //多余,缩小区间
      int newr=r+toleft[pos][R]-toleft[pos][r]; //查询区间向右移
      int newl=newr-(r-l-cnt);
      return query(mid+1,R,newl,newr,pos+1,k-cnt);
   }
}
int main(){
    int n,m,i,j,k,a,b,c,t;
    scanf("%d",&t);
    while(t--){
        memset(tree,0,sizeof(tree));
       scanf("%d%d",&n,&m);
       for(i=1;i<=n;i++) {
            scanf("%d",&tree[0][i]); //顶层
            as[i]=tree[0][i];
       }
       sort(as+1,as+n+1); //快排
       build(1,n,0);
       for(i=0;i<m;i++){
         scanf("%d%d%d",&a,&b,&c);
         printf("%d\n",query(1,n,a,b,0,c));
       }
    }
    return 0;
}

 

hdu 2665 Kth number(划分树)

标签:

原文地址:http://www.cnblogs.com/dominatingdashuzhilin/p/4733524.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!