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

【9018:2208】可持久化线段树2

时间:2018-03-08 17:18:23      阅读:136      评论:0      收藏:0      [点我收藏+]

标签:ems   scanf   时间   space   define   family   names   style   submit   

2208: 【模板】可持久化线段树2

时间限制: 3 Sec 内存限制: 256 MB
提交: 30 解决: 12
[提交][状态][讨论版]

题目描述

静态区间第K小问题是典型的主席树模板。

在这个问题中,你需要实现对区间第K小的查询。

输入

第1行,输入两个正整数n,m,表示数列长度,查询次数。

第2行,n个整数表示数列ai。

接下来m行,每行3个正整数l,r,k表示查询[l,r]内的第k小数。(1<=l<=r<=n,1<=k<=r-l+1)

输出

输出m行,每行1个整数表示答案。

样例输入

5 5
25957 6405 15770 26287 26465 
2 2 1
3 4 1
4 5 1
1 2 2
4 4 1

样例输出

6405
15770
26287
25957
26287

提示

对于100%的数据满足:1≤N,M≤5?1051 \leq N, M \leq 2\cdot 10^5

对于数列中的所有数aia_i,均满足?109≤ai≤109-{10}^9 \leq a_i \leq {10}^9

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#define MN 500005
#define MM 10000005
using namespace std;
int n,q,v[MN],rk[MN],vv[MN],cnt,T[MM],ls[MM],rs[MM],rt[MM];
bool cmp(int x,int y){return v[x]<v[y];}
void update(int &k,int l,int r,int v){
    ls[++cnt]=ls[k],rs[cnt]=rs[k],k=cnt;
    if(l==r){T[k]=1;return;}
    int mid=(l+r)>>1;
    if(v<=mid) update(ls[k],l,mid,v);
    else update(rs[k],mid+1,r,v);
    T[k]=T[ls[k]]+T[rs[k]];
}
int query(int k,int l,int r,int ql,int qr){
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(k<=T[ls[qr]]-T[ls[ql]]) return query(k,l,mid,ls[ql],ls[qr]);
    else return query(k-=T[ls[qr]]-T[ls[ql]],mid+1,r,rs[ql],rs[qr]);
}
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++) scanf("%d",&v[i]),rk[i]=i;
    sort(rk+1,rk+1+n,cmp);
    for(int i=1;i<=n;i++) vv[rk[i]]=i;
    //for(int i=1;i<=n;i++) printf("%d\n",rk[i]);
    for(int i=1;i<=n;i++) rt[i]=rt[i-1],update(rt[i],1,n,vv[i]);
    for(int i=1;i<=q;i++){
        int x,y,k; scanf("%d%d%d",&x,&y,&k);
        printf("%d\n",v[rk[query(k,1,n,rt[x-1],rt[y])]]);
    }
    return 0;
}

 

【9018:2208】可持久化线段树2

标签:ems   scanf   时间   space   define   family   names   style   submit   

原文地址:https://www.cnblogs.com/Beginner-/p/8529053.html

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