P9970 题解
masterhuang · · 题解
推销博客!第
前置知识:P4137 的在线单次
赛事做繁了,没冲出来。发现第二篇题解难理解,第一篇题解有个细节繁了,于是我结合了一下。除去主席树板子,代码非常短。
这篇题解是目前第一篇题解和第二篇的结合,由重合请见谅。
如果不想看结论证明直接忽略即可,没啥影响。
称
- 证明:设
[l,r] 是极小区间,则显然a_l\neq a_r ,不妨设a_l>a_r ,则由于删掉端点\text{mex} 要变化,于是\text{mex}(l,r)>a_l>a_r 。若存在r_1>r ,[l,r_1] 是极小区间,则\text{mex}(l,r)\ge a_l>a_{r_1} ,于是a_{r_1} 在[l,r] 中出现过。于是删去a_{r_1} ,\text{mex} 不变。于是固定l ,a_l>a_r 的情况只对应一个r ,所以只有O(n) 个了。
考虑如何求所有极小区间。如果直接按证明方法求是非常难写的。于是考虑巧妙方法。
设
考虑一个
考虑删去
- 这说明:
\text{mex}_x 区间必定为一个\text{mex}_{t} 区间向一端扩展到第一个数t 得到。其中x>t 。
考虑从
每次先把所有
这时候所有
由于极小区间总共只有
求出所有极小区间后,考虑所有对应
设
则所有对应的大区间为:左端点在
于是问题就转化成了:维护
代码:
#include<bits/stdc++.h>
#define LL long long
#define P pair<int,int>
#define fi first
#define se second
#define fr(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
using namespace std;
const int N=1e5+5;
int n,V,a[N],cnt[N],tot,rt[N];
vector<int>g[N],ad[N],dl[N];vector<P>h[N];
namespace MEX
{
struct node{int ls,rs,x;}b[N*25];
void build(int l,int r,int &wz)
{
b[wz=++tot]={0,0,0};if(l==r) return;
int mid=(l+r)>>1;build(l,mid,b[wz].ls);build(mid+1,r,b[wz].rs);
}
void updata(int l,int r,int &wz,int wz1,int x,int y)
{
b[wz=++tot]=b[wz1];if(l==r) return b[wz].x=y,void();
int mid=(l+r)>>1;
if(x<=mid) updata(l,mid,b[wz].ls,b[wz1].ls,x,y);
else updata(mid+1,r,b[wz].rs,b[wz1].rs,x,y);
b[wz].x=min(b[b[wz].ls].x,b[b[wz].rs].x);
}
int query(int l,int r,int wz,int x)
{
if(l==r) return l;int mid=(l+r)>>1;
if(b[b[wz].ls].x<x) return query(l,mid,b[wz].ls,x);
return query(mid+1,r,b[wz].rs,x);
}
inline int que(int l,int r){return query(0,V,rt[r],l);}
}using MEX::que;
int vis[1005][1005];
inline void add(int l,int r,int L,int R,int x){ad[L-r+1].push_back(x);dl[R-l+2].push_back(x);}
inline void getans()
{
set<int>S;for(int i=0;i<=n;i++) cnt[i]=0,S.insert(i);
for(int i=1;i<=n;i++)
{
for(int j:ad[i]) if(!cnt[j]++) S.erase(j);
for(int j:dl[i]) if(!--cnt[j]) S.insert(j);cout<<*S.begin()<<" ";
}
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n;
V=n+3;for(int i=0;i<=V;i++) g[i].push_back(0);
for(int i=1;i<=n;i++) cin>>a[i],g[a[i]].push_back(i);
MEX::build(1,V,rt[0]);for(int i=1;i<=n;i++) MEX::updata(0,V,rt[i],rt[i-1],a[i],i);
for(int i=0;i<=V;i++) g[i].push_back(n+1);
for(int i=1;i<=n;i++) a[i]?h[0].push_back({i,i}):h[1].push_back({i,i});
for(int i=1;i<=V;i++)
{
for(auto [l,r]:h[i-1])
{
#define all g[i-1].begin(),g[i-1].end()
int L=*(--lower_bound(all,l)),R=*upper_bound(all,r);
if(L) h[que(L,r)].push_back({L,r});
if(R<=n) h[que(l,R)].push_back({l,R});
}sort(h[i].begin(),h[i].end(),[](P x,P y){return x.fi==y.fi?x.se<y.se:x.fi>y.fi;});
vector<P>G;int las=2e9;
for(auto [l,r]:h[i]) if(las>r) G.push_back({l,r}),las=r;swap(G,h[i]);
}
for(int i=0;i<=V;i++)
for(auto [l,r]:h[i])
#define all g[i].begin(),g[i].end()
add(*(--lower_bound(all,l))+1,l,r,*upper_bound(all,r)-1,i);
return getans(),0;
}