Problem Description
Mex is a function on a set of integers, which is universally used for impartial game theorem. For a non-negative integer set S, mex(S) is defined as the least non-negative integer which is not appeared in S. Now our problem is about mex function on a sequence.
Consider a sequence of non-negative integers {ai}, we define mex(L,R) as the least non-negative integer which is not appeared in the continuous subsequence from aL to aR, inclusive. Now we want to calculate the sum of mex(L,R) for all 1 <= L <= R <= n.
Input
The input contains at most 20 test cases.
For each test case, the first line contains one integer n, denoting the length of sequence.
The next line contains n non-integers separated by space, denoting the sequence.
(1 <= n <= 200000, 0 <= ai <= 10^9)
The input ends with n = 0.
Output
For each test case, output one line containing a integer denoting the answer.
Sample Input
3
0 1 3
5
1 0 2 0 1
0
Sample Output
5
24
Hint
For the first test case:
mex(1,1)=1, mex(1,2)=2, mex(1,3)=2, mex(2,2)=0, mex(2,3)=0,mex(3,3)=0.
1 + 2 + 2 + 0 +0 +0 = 5.
Source
2013 ACM/ICPC Asia Regional Hangzhou Online
想不到怎么都想不出来,还是看了题解才知道的,先O(n)处理一在次1开头的情况,然后i往后移的时候,更新a[i]与下一个a[i]之间的值,下一个a[i]之后就没有影响了。因为去掉了a[i],所以比a[i]大的值更新为a[i],每次update之后答案就是sum[root]。
要在build的时候更新sum,flag,maxn的值,我都忘了是要乘4倍的,wa了好几次QAQ
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<vector>
using namespace std;
#define ll long long
const int inf=1e9+5;
ll mex[200005*4],sum[200005*4],flag[200005*4],maxn[200005*4];
void pushup(int root)
{
sum[root]=sum[root<<1]+sum[root<<1|1];
maxn[root]=max(maxn[root<<1],maxn[root<<1|1]);
}
void pushdown(int l,int r,int root)
{
int mid=l+r>>1;
if(flag[root]==-1)
return ;
sum[root<<1]=(ll)(mid-l+1)*flag[root];
sum[root<<1|1]=(ll)(r-mid)*flag[root];
flag[root<<1]=flag[root<<1|1]=flag[root];
maxn[root<<1]=maxn[root<<1|1]=flag[root];
flag[root]=-1;
}
void build(int l,int r,int root)
{
maxn[root]=sum[root]=0;
flag[root]=-1;
if(l==r)
{
maxn[root]=sum[root]=mex[l];
return ;
}
int mid=l+r>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
pushup(root);
}
void update(int l,int r,int root,int ql,int qr,int val)
{
if(l>=ql&&r<=qr)
{
sum[root]=(ll)(r-l+1)*val;
flag[root]=maxn[root]=(ll)val;
return ;
}
pushdown(l,r,root);
int mid=l+r>>1;
if(mid>=ql)
update(l,mid,root<<1,ql,qr,val);
if(mid<qr)
update(mid+1,r,root<<1|1,ql,qr,val);
pushup(root);
}
int query(int l,int r,int root,int val)
{
if(val>maxn[root])
return inf;
if(l==r)
return l;
int mid=l+r>>1;
int ans=query(l,mid,root<<1,val);
if(ans>=inf)
ans=query(mid+1,r,root<<1|1,val);
return ans;
}
vector<int>vec[200005];
int vis[200005],cnt[200005],a[200005];
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
for(int i=0;i<200005;i++)
{
vis[i]=cnt[i]=0;
vec[i].clear();
}
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]>n)
a[i]=n+1;
vec[a[i]].push_back(i);
}
int pos=0;
ll ans=0;
for(int i=1;i<=n;i++)
{
vis[a[i]]=1;
while(vis[pos])
pos++;
mex[i]=pos;
ans+=mex[i];
}
build(1,n,1);
for(int i=1;i<=n;i++)
{
cnt[a[i]]++;
int fin;
if(cnt[a[i]]<vec[a[i]].size())
fin=vec[a[i]][cnt[a[i]]]-1;
else
fin=n;
int sta=query(1,n,1,a[i]);
if(sta<=fin)
update(1,n,1,sta,fin,a[i]);
ans+=sum[1];
}
printf("%lld\n",ans);
}
return 0;
}