点名

【题目描述】

 

在 J 班的体育课上,同学们常常会迟到几分钟,但体育老师的点名却一直很准时。

 

老师只关心同学的身高,他会依次询问当前最高的身高,次高的身高,第三高的身高,

 

等等。在询问的过程中,会不时地有人插进队伍里。你需要回答老师每次的询问。

 

【输入格式】

 

第一行两个整数 n m,表示先后有 n 个人进队,老师询问了 m 次

 

第二行 n 个整数,第 i 个数 Ai 表示第 i 个进入队伍的同学的身高为 Ai

 

第三行 m 个整数,第 j 个数 Bj 表示老师在第 Bj 个同学进入队伍后有一次询问

 

【输出格式】

 

m 行,每行一个整数,依次表示老师每次询问的答案。数据保证合法

 

【样例输入】

 

7 4

 

9 7 2 8 14 1 8

 

1 2 6 6

 

【样例输出】

 

9

 

9

 

7

 

8

 

【样例解释】

 

(9){No.1 = 9}; (9 7){No.2 = 9}; (9 7 2 8 14 1){No.3 = 7; No.4 = 8}

 

【数据范围】

 

40%的数据保证 n ≤ 1000

 

100%的数据保证 1 ≤ m ≤ n ≤ 30000; 0 ≤ Ai < 232

 

//又是主席树模板啊,最喜欢这样的题了!
//换种写法 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define maxn 30010
#define maxm 1000010

using namespace std;
ll n,m,cnt,num,a[maxn],root[maxn],order[maxn];
struct node{
    ll lc,rc,sum;
}t[maxm*5];

ll Build(ll S,ll L,ll R)
{
    ll k=++cnt;
    t[k].sum=S;
    t[k].lc=L;t[k].rc=R;
    return k;
}

void insert(ll &root,ll pre,ll pos,ll l,ll r)
{
    root=Build(t[pre].sum+1,t[pre].lc,t[pre].rc);
    if(l==r)return;
    ll mid=(l+r)/2;
    if(pos<=mid)insert(t[root].lc,t[pre].lc,pos,l,mid);
    else insert(t[root].rc,t[pre].rc,pos,mid+1,r);
}

ll Query(ll L,ll R,ll pos,ll l,ll r)
{
    if(l==r)return l;
    ll sum=t[t[R].lc].sum-t[t[L].rc].sum;
    ll mid=(l+r)/2;
    if(sum>=pos)return Query(t[L].lc,t[R].lc,pos,l,mid);
    else return Query(t[L].rc,t[R].rc,pos-sum,mid+1,r);
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        order[i]=a[i];
    }
    sort(order+1,order+n+1);
    num=unique(order+1,order+n+1)-order-1;
    for(int i=1;i<=n;i++)
    {
        ll pos=lower_bound(order+1,order+num+1,a[i])-order;
        insert(root[i],root[i-1],pos,1,num);
    }
    ll l,r,k;
    for(int i=1;i<=n;i++)
    {
        l=1;scanf("%lld",&r);k=i;
        ll p=Query(root[l-1],root[r],k,1,num);
        printf("%lld\n",order[p]);
    }
    return 0;
} 
心若向阳,无言悲伤

 

转载于:https://www.cnblogs.com/L-Memory/p/6289712.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值