poj 2104

区间第K小 刚刚学的划分树

感觉树的作用就是 n^2  -> n logn

分治一下  划分成左右2个子树 然后小的左边  大的右边

#include <iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<math.h>

using namespace std ;

#define e 2.7182818284
#define LL __int64
#define MAXN 200010
#define inf  1000000000

struct node
{
    int val[MAXN];//当前这一层的第i个位置的值
    int num[MAXN];//到i这个位子应该进入左子树的数目
}t[20];           //划分成左右的化不会超过20层
int sorted[MAXN]; //排序后的数组
void Build(int l,int r,int ind) //建树  左右区间 然后层数
{
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    int lsame = mid-l+1,same=0,ln=l,rn=mid+1;//lsame 代表到左子树的数目  下面有用  其实是算出到左边满了没有
    for(int i=l;i<=r;i++)
        if(t[ind].val[i]<sorted[mid]) //小的话显然是要去的
            lsame--;
    for(int i=l;i<=r;i++)
    {
        if(i==l)
            t[ind].num[i]=0;
        else
            t[ind].num[i]+=t[ind].num[i-1];
        if(t[ind].val[i]<sorted[mid])
            t[ind].num[i]++,t[ind+1].val[ln++]=t[ind].val[i];//小的话去左边 然后左子树的值附上
        else if(t[ind].val[i]>sorted[mid])
            t[ind+1].val[rn++]=t[ind].val[i];
        else
        {
            same++;
            if(lsame>=same)
                t[ind].num[i]++,t[ind+1].val[ln++]=t[ind].val[i]; //这边是左边还能去
            else
                t[ind+1].val[rn++] = t[ind].val[i];
        }
    }
    Build(l,mid,ind+1);
    Build(mid+1,r,ind+1);
}
int ques(int st, int ed, int k, int l,int r, int ind)
{
    if(l==r)
        return t[ind].val[l];
    int lx,ly,rx,ry,mid = (l + r)>>1;
    if(st == l)
        lx = 0, ly = t[ind].num[ed];
    else
        lx = t[ind].num[st - 1],ly = t[ind].num[ed] - t[ind].num[st - 1];
if(ly >= k) //左子树大了 { st = l + lx; ed = l + lx + ly -1; return ques(st,ed,k,l,mid, ind+1); } else //去掉左子树的那段 从右边那段开始 { rx = st - 1 - l + 1 - lx; ry = ed - st + 1 - ly; st = mid + 1 + rx; ed = mid + 1 + rx + ry - 1; return ques(st,ed,k - ly, mid + 1,r,ind + 1); } } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&sorted[i]); t[0].val[i]=sorted[i]; } sort(sorted+1,sorted+n+1); Build(1,n,0); while(m--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); int ans=ques(a,b,c,1,n,0); printf("%d\n",ans); } return 0; }

 

posted on 2017-03-04 11:08  HelloWorld!--By-MJY  阅读(125)  评论(0编辑  收藏  举报

导航