求区间 mex
莫队+分块
值域分块,每个块处理有多少个书出现过。
#include <bits/stdc++.h>
using namespace std;
inline void read(int& x)
{
x=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<1)+(x<<3)+c-'0';
c=getchar();
}
x*=f;
}
const int N=2e5+5,B=448;
int n,m,a[N],id[N],block,cnt[N],num[N];
int ans[N];
struct node
{
int l,r,id;
}q[N];
bool cmp(node u,node v)
{
if(id[u.l]==id[v.l])return u.r<v.r;
return id[u.l]<id[v.l];
}
void del(int x)
{
if(cnt[x]==1)num[x/B]--;
cnt[x]--;
}
void add(int x)
{
if(cnt[x]==0)num[x/B]++;
cnt[x]++;
}
void query(int x)
{
for(int i=1;i<=B;i++)
if(num[i-1]!=B)for(int j=(i-1)*B;j<i*B;j++)if(!cnt[j])ans[x]=j;return;}
}
int main()
{
read(n),read(m);
block=sqrt(n);
for(int i=1;i<=n;i++)
{
read(a[i]);
id[i]=(i-1)/block+1;
}
for(int i=1;i<=m;i++)
{
read(q[i].l),read(q[i].r);
q[i].id=i;
}
sort(q+1,q+m+1,cmp);
int l=q[1].l,r=q[1].r;
for(int i=l;i<=r;i++)add(a[i]);
query(q[1].id);
for(int i=2;i<=m;i++)
{
while(l<q[i].l)del(a[l++]);
while(l>q[i].l)add(a[--l]);
while(r<q[i].r)add(a[++r]);
while(r>q[i].r)del(a[r--]);
query(q[i].id);
}
for(int i=1;i<=m;i++)
{
cout<<ans[i]<<'\n';
}
return 0;
}
可持久化线段树
维护每个数在第 \(i\) 个历史前,最后一次出现的位置
对于查询 \([l,r]\),在第 \(r\) 个历史版本中找到 最后一次在第 \(l\) 个历史版本最小值。
#include <bits/stdc++.h>
using namespace std;
const int N=3e5+5,mx=3e5;
int n,m,b[N];
struct node
{
int val,ls,rs;
}t[N*40];
int idx=0,rt[N];
namespace tree
{
inline void upd(int &p,int pre,int l,int r,int x,int k)
{
p=++idx;
t[p]=t[pre];
if(l==r) { t[p].val=k; return; }
int mid=(l+r)/2;
if(x<=mid)upd(t[p].ls,t[pre].ls,l,mid,x,k);
else upd(t[p].rs,t[pre].rs,mid+1,r,x,k);
t[p].val=min(t[t[p].ls].val,t[t[p].rs].val);
}
inline int query(int p,int l,int r,int k)
{
if(l==r)return l;
int mid=(l+r)/2;
if(t[t[p].ls].val<k)return query(t[p].ls,l,mid,k);//如果左子树的值域中,有最近一次出现的时间<当前查询的k时刻的点,就确定是左子树
else return query(t[p].rs,mid+1,r,k);//否之,去右子树
}
inline int mex(int l,int r)
{
if(l>r)return 0;
return query(rt[r],0,n,l);//查询
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>b[i];
tree::upd(rt[i],rt[i-1],0,n,b[i],i);
}
while(m--)
{
int st,en;
cin>>st>>en;
cout<<tree::mex(st,en)<<'\n';
}
return 0;
}

浙公网安备 33010602011771号