题解:
f
i
=
max
j
{
min
{
a
i
−
a
j
,
b
i
−
b
j
}
+
f
j
+
1
}
(
j
<
i
,
p
j
<
i
)
f_i = \max_j \{\min \{a_i-a_j,b_i-b_j\}+f_j+1\} (j \lt i, p_j \lt i)
fi=jmax{min{ai−aj,bi−bj}+fj+1}(j<i,pj<i)
其中
a
i
a_i
ai为没有填的数中比
p
i
p_i
pi小的数,
b
b
b为前缀0的个数。
CDQ分治+树状数组解决三维偏序。
#include <bits/stdc++.h>
using namespace std;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=1e5+50, L=1e5+2, INF=0x3f3f3f3f;
int n,m,ans;
int p[N],a[N],b[N],f[N];
int bit[2][N*2];
inline void inc_up(int *bit,int p,int val) {for(p+=L;p<=2*L;p+=p&(-p)) bit[p]=max(bit[p],val);}
inline void inc_down(int *bit,int p,int val) {for(p+=L;p;p-=p&(-p)) bit[p]=max(bit[p],val);}
inline int ask_up(int *bit,int p,int rs=-INF) {for(p+=L;p<=2*L;p+=p&(-p)) rs=max(rs,bit[p]); return rs;}
inline int ask_down(int *bit,int p,int rs=-INF) {for(p+=L;p;p-=p&(-p)) rs=max(rs,bit[p]); return rs;}
inline void del_up(int *bit,int p) {for(p+=L;p<=2*L;p+=p&(-p)) bit[p]=-INF;}
inline void del_down(int *bit,int p) {for(p+=L;p;p-=p&(-p)) bit[p]=-INF;}
inline void solve(int l,int r) {
if(l==r) return;
int mid=(l+r)>>1;
solve(l,mid);
vector <int> op;
for(int i=l;i<=r;i++) if(i==0 || p[i]) op.push_back(i);
sort(op.begin(),op.end(),[&](const int &i,const int &j) {return p[i]<p[j];});
for(auto i:op) {
if(i<=mid) {
inc_down(bit[0],a[p[i]]-b[i],f[i]-a[p[i]]);
inc_up(bit[1],a[p[i]]-b[i],f[i]-b[i]);
} else {
f[i]=max(f[i],ask_up(bit[0],a[p[i]]-b[i])+a[p[i]]+1);
f[i]=max(f[i],ask_down(bit[1],a[p[i]]-b[i])+b[i]+1);
}
}
for(auto i:op) if(i<=mid) del_down(bit[0],a[p[i]]-b[i]), del_up(bit[1],a[p[i]]-b[i]);
solve(mid+1,r);
}
int main() {
n=rd(); m=n;
for(int i=1;i<=2*L;i++) bit[0][i]=bit[1][i]=-INF;
for(int i=1;i<=n;i++) a[i]=1;
for(int i=1;i<=n;i++) p[i]=rd(), (p[i] && (--m,--a[p[i]]));
for(int i=1;i<=n;i++) a[i]+=a[i-1];
for(int i=1;i<=n;i++) b[i]=b[i-1]+(!p[i]);
p[0]=0; solve(0,n);
for(int i=0;i<=n;i++) if(i==0 || p[i]) ans=max(ans,f[i]+min(m-a[p[i]],m-b[i]));
cout<<ans<<'\n';
}