Problem
Description
Input
Output
Sample Input
3
0 1 3
Sample Output
5
Data Constraint
Solution
我们不要看到
0≤ai≤109
就怕,其实开数组就开一个200000的就OK了。
首先我们求出mex(1,i)。我们可以发现,mex(1,i)是单调递增的。
怎么求mex(1,i)?
设序列数组为c,对于每一个读入的
ci
,只需要处理≤n的
ci
(想一想为什么)。
然后开next数组来方便求出下一个c[i]的位置。
fo(i,1,n)
{
if (c[i]<=n)
{
next[bz[c[i]]]=i;
bz[c[i]]=i;
}
while (bz[p]) p++;
}
然后再求mex(2,i),mex(3,i)….每一次删除掉一个数x,那么在下一个x出现前的>x的mex值都要变成x。
我们利用mex数列的单调递增性,每次找到第一个mex>x的位置,记为wz,那么将wz~next[i]的所有mex值全部变成x。
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define N 200010
#define LL long long
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int bz[N],next[N];
LL tree[N*10][3];
int i,j,k,n,m,p,bj;
long long ans,c[N],_1[N];
void build(int s,int l,int r)
{
tree[s][0]=-1;
if (l==n) bj=s;
if (l==r)
{
tree[s][1]=tree[s][2]=_1[l];
return;
}
int wz=(l+r)/2;
build(s*2,l,wz);
build(s*2+1,wz+1,r);
tree[s][1]=max(tree[s*2][1],tree[s*2+1][1]);
tree[s][2]=tree[s*2][2]+tree[s*2+1][2];
}
int find(int s,int l,int r,int x)
{
if (l==r) return l;
int wz=(l+r)/2;
if (tree[s][0]!=-1)
{
tree[s*2][0]=tree[s*2][1]=tree[s][0];
tree[s*2+1][0]=tree[s*2+1][1]=tree[s][0];
tree[s*2][2]=(wz-l+1)*tree[s][0];
tree[s*2+1][2]=(r-wz)*tree[s][0];
tree[s][0]=-1;
}
if (tree[s*2][1]>x) return find(s*2,l,wz,x);
else return find(s*2+1,wz+1,r,x);
tree[s][1]=max(tree[s*2][1],tree[s*2+1][1]);
tree[s][2]=tree[s*2][2]+tree[s*2+1][2];
}
void change(int s,int l,int r,int x,int y,LL z)
{
if (l==x && r==y)
{
tree[s][0]=tree[s][1]=z;
tree[s][2]=z*(r-l+1);
return;
}
int wz=(l+r)/2;
if (tree[s][0]!=-1)
{
tree[s*2][0]=tree[s*2][1]=tree[s][0];
tree[s*2+1][0]=tree[s*2+1][1]=tree[s][0];
tree[s*2][2]=(wz-l+1)*tree[s][0];
tree[s*2+1][2]=(r-wz)*tree[s][0];
tree[s][0]=-1;
}
if (y<=wz) change(s*2,l,wz,x,y,z);
else if (x>wz) change(s*2+1,wz+1,r,x,y,z); else
{
change(s*2,l,wz,x,wz,z);
change(s*2+1,wz+1,r,wz+1,y,z);
}
tree[s][1]=max(tree[s*2][1],tree[s*2+1][1]);
tree[s][2]=tree[s*2][2]+tree[s*2+1][2];
}
void search(int s,int l,int r,int x,int y)
{
if (l==x && r==y)
{
ans+=tree[s][2];
return;
}
int wz=(l+r)/2;
if (tree[s][0]!=-1)
{
tree[s*2][0]=tree[s*2][1]=tree[s][0];
tree[s*2+1][0]=tree[s*2+1][1]=tree[s][0];
tree[s*2][2]=(wz-l+1)*tree[s][0];
tree[s*2+1][2]=(r-wz)*tree[s][0];
tree[s][0]=-1;
}
if (y<=wz) search(s*2,l,wz,x,y);
else if (x>wz) search(s*2+1,wz+1,r,x,y); else
{
search(s*2,l,wz,x,wz);
search(s*2+1,wz+1,r,wz+1,y);
}
tree[s][1]=max(tree[s*2][1],tree[s*2+1][1]);
tree[s][2]=tree[s*2][2]+tree[s*2+1][2];
}
int main()
{
scanf("%d",&n);
fo(i,1,n) scanf("%lld",&c[i]);
fo(i,1,n)
{
if (c[i]<=n)
{
next[bz[c[i]]]=i;
bz[c[i]]=i;
}
while (bz[p]) p++;
_1[i]=p;
ans+=p;
}
build(1,1,n);
fo(i,1,n-1)
{
if (next[i]==0) next[i]=n+1;
k=find(1,1,n,c[i]);
if (tree[bj][1]<c[i]) k=n+1;
if (k<=next[i]-1) change(1,1,n,k,next[i]-1,c[i]);
search(1,1,n,i+1,n);
}
printf("%lld",ans);
}
——2016.8.11