题目链接:HDU - 4747
每次枚举右端点,加入一个数字,维护每个位置的mex,显然很复杂。
所以我们考虑每次删除一个左端点,维护前缀mex。
考虑当前位置的影响,会影响到后面大于 a[i] 的mex,会变成 a[i] ,直到下一个 a[i] ,所以线段树维护区间修改即可,因为答案是单调递增的,所以线段树区间赋值即可,不用segment beats。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int n,mx[N<<2],a[N],sum[N<<2],lazy[N<<2],mex[N],cnt,pos[N],res; map<int,int> mp,vis;
#define mid (l+r>>1)
inline void push_up(int p){
sum[p]=sum[p<<1]+sum[p<<1|1];
mx[p]=max(mx[p<<1],mx[p<<1|1]);
}
void build(int p,int l,int r){
lazy[p]=-1;
if(l==r){mx[p]=sum[p]=mex[l]; return ;}
build(p<<1,l,mid),build(p<<1|1,mid+1,r);
push_up(p);
}
inline void upd(int p,int l,int r,int v){sum[p]=(r-l+1)*v,mx[p]=v,lazy[p]=v;}
inline void push_down(int p,int l,int r){
if(lazy[p]!=-1) upd(p<<1,l,mid,lazy[p]),upd(p<<1|1,mid+1,r,lazy[p]),lazy[p]=-1;
}
void change(int p,int l,int r,int ql,int qr,int v){
if(l==ql&&r==qr) return upd(p,l,r,v),void();
push_down(p,l,r);
if(qr<=mid) change(p<<1,l,mid,ql,qr,v);
else if(ql>mid) change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
push_up(p);
}
int ask(int p,int l,int r,int ql,int qr){
if(l==ql&&r==qr) return sum[p];
push_down(p,l,r);
if(qr<=mid) return ask(p<<1,l,mid,ql,qr);
else if(ql>mid) return ask(p<<1|1,mid+1,r,ql,qr);
else return ask(p<<1,l,mid,ql,mid)+ask(p<<1|1,mid+1,r,mid+1,qr);
}
int query(int p,int l,int r,int ql,int qr,int v){
if(l==r) return l;
push_down(p,l,r);
if(qr<=mid) return query(p<<1,l,mid,ql,qr,v);
else if(ql>mid) return query(p<<1|1,mid+1,r,ql,qr,v);
else{
if(mx[p<<1]>v) return query(p<<1,l,mid,ql,mid,v);
else return query(p<<1|1,mid+1,r,mid+1,qr,v);
}
}
void solve(){
cnt=res=0; vis.clear(); mp.clear();
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=n;i>=1;i--){
if(!mp.count(a[i])) pos[i]=n+1;
else pos[i]=mp[a[i]];
mp[a[i]]=i;
}
for(int i=1;i<=n;i++){
vis[a[i]]=1;
while(vis.count(cnt)) cnt++;
mex[i]=cnt;
}
build(1,1,n);
for(int i=1;i<=n;i++){
res+=ask(1,1,n,i,n);
if(ask(1,1,n,pos[i]-1,pos[i]-1)<=a[i]) continue;
int p=query(1,1,n,i,n,a[i]);
if(p<pos[i]) change(1,1,n,p,pos[i]-1,a[i]);
}
cout<<res<<endl;
}
signed main(){
while(cin>>n,n) solve();
return 0;
}