我的树状数组怎么那么慢啊
就是一道水题,我们考虑一下对于一个区间([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
",min(Ans[i],ans));
return 0;
}