【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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章