【bzoj 3339】Rmq Problem & 【bzoj 3585】mex(可持久化线段树)

传送门biu~biu~
两道题区别只在于ai的范围,显然>=n的那些ai都是没有意义的,因此两题相同。
权值线段树上的i点记录数字i的最右出现位置,查询区间[l,r]即为查询第r棵线段树上最小的i满足i最右出现的位置

#include<bits/stdc++.h>
#define N 200005
using namespace std;
struct Node{
    Node *ch[2];int Min;
    Node();
    void maintain(){Min=min(ch[0]->Min,ch[1]->Min);}
}*null=new Node,*root[N];
Node::Node():Min(0){
    ch[0]=ch[1]=null;
}
inline void init(){
    null->ch[0]=null->ch[1]=null;
    root[0]=new Node;
}
void build(Node *u,Node *&o,int l,int r,int x,int v){
    o=new Node;
    if(l==r){
        o->Min=v;
        return;
    }
    int mid=l+r>>1;
    if(x<=mid){
        build(u->ch[0],o->ch[0],l,mid,x,v);
        o->ch[1]=u->ch[1];
    }
    else{
        o->ch[0]=u->ch[0];
        build(u->ch[1],o->ch[1],mid+1,r,x,v);
    }
    o->maintain();
}
int Query(Node *o,int l,int r,int v){
    if(l==r)    return r;
    int mid=l+r>>1;
    if(o->ch[0]->Min>=v) return Query(o->ch[1],mid+1,r,v);
    else return Query(o->ch[0],l,mid,v);
}
int main(){
    init();int n,T;
    scanf("%d%d",&n,&T);
    for(int x,i=1;i<=n;++i){
        scanf("%d",&x);
        if(x>n) root[i]=root[i-1];
        else build(root[i-1],root[i],0,n,x,i);
    }
    while(T--){
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",Query(root[r],0,n,l));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zP1nG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值