http://acm.hust.edu.cn/vjudge/contest/view.action?cid=78124#problem/B
//想看题目的@willinglive
因为mex有单调性,所以我们用线段树来维护以每个点为右端点的mex的和。然后枚举左端点。修改左端点的时候只需要修改当前到下一次该点的值出现的位置-1就可以了
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int a[200001],v[200001],last[200001],nextx[200001];
long long mex[200001];
int n;
struct num
{
int x,t;
}b[200001];
inline bool cmp(num x,num y)
{
if(x.x<y.x)
return true;
return false;
}
struct tree
{
int l,r;
long long s;
long long mi,ma;
long long tag;
}tr[1600001];
inline void up(int p)
{
tr[p].s=tr[p*2].s+tr[p*2+1].s;
tr[p].mi=min(tr[p*2].mi,tr[p*2+1].mi);
tr[p].ma=max(tr[p*2].ma,tr[p*2+1].ma);
}
inline void push(int p)
{
if(tr[p].tag==-1)
return ;
long long len=(tr[p].r-tr[p].l+1);;
tr[p*2].s=tr[p].tag*(len-len/2);
tr[p*2+1].s=tr[p].tag*(len/2);
tr[p*2].mi=tr[p].tag;
tr[p*2+1].mi=tr[p].tag;
tr[p*2].ma=tr[p].tag;
tr[p*2+1].ma=tr[p].tag;
tr[p*2].tag=tr[p].tag;
tr[p*2+1].tag=tr[p].tag;
tr[p].tag=-1;
}
inline void build(int p,int l,int r)
{
tr[p].l=l;
tr[p].r=r;
if(l!=r)
{
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
up(p);
tr[p].tag=-1;
}
else
{
tr[p].s=mex[l];
tr[p].mi=mex[l];
tr[p].ma=mex[l];
tr[p].tag=-1;
}
}
inline void cover(int p,int l,int r,int x)
{
if((l<=tr[p].l&&tr[p].r<=r&&tr[p].mi>x))
{
long long len=(tr[p].r-tr[p].l+1);
tr[p].tag=x;
tr[p].s=x*len;
tr[p].mi=x;
tr[p].ma=x;
}
else if(tr[p].ma<x)
return ;
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
cover(p*2,l,r,x);
if(r>mid)
cover(p*2+1,l,r,x);
up(p);
}
}
inline void change(int p,int l,int r,int x)
{
if(l<=tr[p].l&&tr[p].r<=r)
{
tr[p].s=x;
tr[p].mi=x;
tr[p].ma=x;
}
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
change(p*2,l,r,x);
if(r>mid)
change(p*2+1,l,r,x);
up(p);
}
}
inline long long ask(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r)
return tr[p].s;
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
long long ans=0;
if(l<=mid)
ans+=ask(p*2,l,r);
if(r>mid)
ans+=ask(p*2+1,l,r);
return ans;
}
}
inline void changex(int x)
{
int i;
int ed=nextx[x];
if(ed==0)
ed=n+1;
mex[x]=0;
change(1,x,x,mex[x]);
cover(1,x+1,ed-1,a[x]);
}
int f[200001];
int fx[200001];
int main()
{
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
scanf("%d",&n);
while(n!=0)
{
int i,j;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i].x=a[i];
b[i].t=i;
}
sort(b+1,b+1+n,cmp);
int tot=1;
f[tot]=0;
fx[0]=tot;
for(i=1;i<=n;i++)
{
if(b[i].x!=f[tot])
{
tot++;
f[tot]=b[i].x;
}
fx[b[i].t]=tot;
}
memset(v,0,sizeof(v));
int now=1;
for(i=1;i<=n;i++)
{
int d;
v[fx[i]]=1;
while(v[now]!=0&&f[now+1]==f[now]+1)
now++;
if(v[now]!=0&&f[now+1]!=f[now]+1)
d=f[now]+1;
else
d=f[now];
mex[i]=d;
}
build(1,1,n);
memset(last,0,sizeof(last));
for(i=1;i<=n;i++)
{
nextx[last[fx[i]]]=i;
nextx[i]=n+1;
last[fx[i]]=i;
}
long long ans=0;
for(i=1;i<=n;i++)
{
ans+=ask(1,i,n);
changex(i);
}
printf("%I64d\n",ans);
scanf("%d",&n);
}
return 0;
}