bzoj 3339 Rmq Problem / mex

题目

我的树状数组怎么那么慢啊

就是一道水题,我们考虑一下对于一个区间\([l,r]\)什么样的数能被计算

显然需要对于一个\(j\),需要满足\(j<l\)\(nxt_{j}>r\),或者\(j>r\)\(lst_j<l\),这样的\(a_j\)才能被计算到

发现这不就是一个数点吗,于是我们扫描线加灵活的树状数组就做完了

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register
#define lb(i) ((i)&(-i))
#define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++)
char BB[1<<18],*S = BB,*T=BB; 
const int maxn=200005;
const int inf=999999999;
inline int read() {
    char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct Ask{int l,r,rk;}q[maxn];
int n,m,ans,sz;
inline int min(int a,int b) {return a<b?a:b;}
int a[maxn],lst[maxn],nxt[maxn],Ans[maxn],ma[maxn],pos[maxn],c[maxn],d[maxn];
inline int cmp(Ask A,Ask B) {return A.l<B.l;}
inline int cop(Ask A,Ask B) {return A.r>B.r;}
inline void change(int x,int val) {for(re int i=x;i;i-=lb(i)) d[i]=min(d[i],val);}
inline void add(int x,int val) {for(re int i=x;i<=n+1;i+=lb(i)) d[i]=min(d[i],val);}
inline int ask(int x) {int now=inf,i;for(i=x;i;i-=lb(i)) now=min(now,d[i]);return now;}
inline int query(int x) {int now=inf,i;x++;for(i=x;i<=n+1;i+=lb(i)) now=min(now,d[i]);return now;}
inline void work() {
    ans=inf;
    if(c[1]!=0) {ans=0;return;}
    for(re int i=2;i<=sz;i++) {
        if(c[i]!=c[i-1]+1) {ans=c[i-1]+1;return;} 
    } 
    ans=c[sz]+1;
}
inline int find(int x) {
    int l=1,r=sz;
    while(l<=r) {
        int mid=l+r>>1;if(c[mid]==x) return mid;
        if(c[mid]<x) l=mid+1;else r=mid-1;
    }
    return 0;
}
int main() {
    n=read(),m=read();
    for(re int i=1;i<=n;i++) c[i]=a[i]=read();
    std::sort(c+1,c+n+1);sz=std::unique(c+1,c+n+1)-c-1;
    for(re int i=n;i;--i) {
        pos[i]=find(a[i]);
        nxt[i]=ma[pos[i]],ma[pos[i]]=i;
    }
    memset(ma,0,sizeof(ma));
    for(re int i=1;i<=n;i++) lst[i]=ma[pos[i]],ma[pos[i]]=i;
    for(re int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].rk=i;
    for(re int i=1;i<=n;i++) if(!nxt[i]) nxt[i]=n+1;
    std::sort(q+1,q+m+1,cmp);
    for(re int i=1;i<=n+1;i++) d[i]=inf;
    for(re int i=1;i<=m;i++) Ans[i]=inf;
    int now=1;
    for(re int i=1;i<=m;i++) {
        while(now<q[i].l) {change(nxt[now],a[now]);now++;}
        Ans[q[i].rk]=min(Ans[q[i].rk],query(q[i].r));
    }
    for(re int i=1;i<=n;i++) d[i]=inf;
    std::sort(q+1,q+m+1,cop);
    now=n;
    for(re int i=1;i<=m;i++) {
        while(now>q[i].r) {add(lst[now]+1,a[now]);now--;}
        Ans[q[i].rk]=min(Ans[q[i].rk],ask(q[i].l));
    }
    work();
    for(re int i=1;i<=m;i++) printf("%d\n",min(Ans[i],ans));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/asuldb/p/10543051.html