A - K-th Number POJ - 2104 -主席树第一弹-第K大的数

  • 感谢:http://www.cnblogs.com/zyf0163/p/4749042.html
  • https://blog.csdn.net/qq_24451605/article/details/49031123
  • 裸题多次查询给定区间L—R内第K大的数
  • #include
    #include
    #include
    using namespace std;
    #define maxn 123456
    struct node
    {
        int l,r,sum;
    } tree[maxn*30];
    int n,cnt,k,snum,a[maxn];
    int m,root[maxn],num[maxn];
    void build(int &u,int l,int r)
    {
        u=++cnt;
        tree[u].sum=0;
        if(l==r)return;
        int mid=(l+r)/2;
        build(tree[u].l,l,mid);
        build(tree[u].r,mid+1,r);
    }
    void updata(int p,int &u,int l,int r,int x)
    {
        u=++cnt;
        tree[u]=tree[p];
        tree[u].sum++;
        int mid=(l+r)/2;
        if(l==r)return;
        if(x>mid)
            updata(tree[p].r,tree[u].r,mid+1,r,x);
        else
            updata(tree[p].l,tree[u].l,l,mid,x);
    }
    int query(int t1,int t2,int l,int r,int k)
    {
        if(l==r)return l;
        int mid=(l+r)/2;
        int lf=tree[tree[t2].l].sum-tree[tree[t1].l].sum;
        if(lf>=k)
            return query(tree[t1].l,tree[t2].l,l,mid,k);
        else
            return query(tree[t1].r,tree[t2].r,mid+1,r,k-lf);
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            cnt=0;
            for(int i=1; i<=n; i++)
            {
                scanf("%d",&a[i]);
                num[i]=a[i];
            }
            sort(num+1,num+n+1);
            snum=unique(num+1,num+1+n)-num-1;
            build(root[0],1,snum);
            for(int i=1; i<=n; i++)
            {
                int x=lower_bound(num+1,num+1+n,a[i])-num;
                updata(root[i-1],root[i],1,snum,x);
            }
            while(m--)
            {
                int l,r,k;
                scanf("%d%d%d",&l,&r,&k);
                int x=query(root[l-1],root[r],1,snum,k);
                printf("%d\n",num[x]);
            }
        }
        return 0;
    }
    

     

你可能感兴趣的:(搜索进阶,线段树)