poj 2104

来源:互联网 发布:浙江古镇旅游攻略 知乎 编辑:程序博客网 时间:2024/06/08 03:59

给定一个区间[l,r],求这个区间的第k大的数是多。

划分树的模板题,讲解见:http://blog.csdn.net/u013983192/article/details/39051671

代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAX 101000#define MID(a,b) (a+((b-a)>>1))int n,m;int sorted[MAX];struct ptree{    int val[MAX];    int num[MAX];};ptree tree[20];void build_tree(int l,int r,int p){    int i,j;    if(l==r) return ;    int mid=MID(l,r);    int lsame=mid-l+1,same=0,ln=l,rn=mid+1;    for(i=l;i<=r;i++) if(tree[p].val[i]<sorted[mid]) lsame--;    for(i=l;i<=r;i++)    {        if(i==l) tree[p].num[i]=0;        else tree[p].num[i]=tree[p].num[i-1];        if(tree[p].val[i]<sorted[mid])        {            tree[p].num[i]++;            tree[p+1].val[ln++]=tree[p].val[i];        }        else if(tree[p].val[i]>sorted[mid])        {            tree[p+1].val[rn++]=tree[p].val[i];        }        else        {            same++;            if(lsame>=same)            {                tree[p].num[i]++;                tree[p+1].val[ln++]=tree[p].val[i];            }            else            {                tree[p+1].val[rn++]=tree[p].val[i];            }        }    }    build_tree(l,mid,p+1);    build_tree(mid+1,r,p+1);}int query(int l,int r,int left,int right,int k,int p){    if(left==right) return tree[p].val[left];    int mid=MID(left,right);    int lx,ly,rx,ry;    /*        lx表示从lft到st-1这段区间内有多少个数进入左子树        ly表示从st到ed这段区间内有多少个数进入左子树        rx表示从lft到st-1这段区间内有多少个数进入右子树        ry表示从st到ed这段区间内有多少个数进入右子树     */    if(l==left)    {        lx=0;ly=tree[p].num[r];    }    else{        lx=tree[p].num[l-1];ly=tree[p].num[r]-lx;    }    if(k<=ly)    {        l=left+lx;        r=left+lx+ly-1;        return query(l,r,left,mid,k,p+1);    }    else    {        rx=l-left-lx;        ry=r-l+1-ly;        l=mid+rx+1;        r=mid+rx+ry;        return query(l,r,mid+1,right,k-ly,p+1);    }}int main(){    int i,j;    int L,R,k;    while(scanf("%d%d",&n,&m)!=EOF)    {        for(i=1;i<=n;i++)        {scanf("%d",&tree[0].val[i]);sorted[i]=tree[0].val[i];}        sort(sorted+1,sorted+n+1);        build_tree(1,n,0);        for(i=1;i<=m;i++)        {            scanf("%d%d%d",&L,&R,&k);            printf("%d\n",query(L,R,1,n,k,0));        }    }    return 0;}


 

0 0