Mex HDU - 4747
定义 mex(S) 为集合 S 中未出现的最小非负整数。
给一个非负整数序列 {ai}i=1n,定义 mex(L,R) 为 aL∼aR 之间未出现的最小非负整数,计算:
1≤L≤R≤n∑mex(L,R)
这题看得我脑壳疼…有两种方法,第一种是线段树,另一种是递推DP。
第二种方法可以看 对hdu4747 Mex 的详解
我尝试再细化一下…
首先令
f[i]=1≤L≤i∑mex(L,i)
则有:
f[i+1]=1≤L≤i+1∑mex(L,i+1)
对于 k≤i,有:
mex(k,i)≤mex(k,i+1)
因此有 f[i]≤f[i+1],假设我们现在已经求出来了 f[i],现在的目标是用 f[i] 推出来 f[i+1],最后的结果就是
res=i=1∑nf[i]
(为了和代码对应,统一往前移一下)用 f[i−1] 来推 f[i] 实际上就是想办法用 mex(k,i−1) 来推 mex(k,i),也就是看加上 a[i] 这个元素,对集合 mex 值的影响,首先找到元素 a[i] 之前出现时所在的下标:last=pos[a[i]],此时能够保证集合 {a[k]∣k∈[last+1,i]} 中 a[i] 是唯一出现的,并且就出现在下标 i 处,而对于 j≤last 对应的集合 {a[k]∣k∈[j,i]} 中 a[i] 不唯一出现,此时可以看到 mex(j,i−1)=mex(j,i) ,因为 a[i] 的作用被前一个他自己给冲掉了。所以考虑用 mex(k,i−1) 来推 mex(k,i) 时只需考虑 k≥last+1 的部分,之前的部分与上一次计算的相同。
所以现在考虑 k≥last+1 时,mex(k,i) 比 mex(k,i−1) 多多少(很容易证明前者 ≥ 后者)。
定义集合 A={0,1,⋯,d},定义 full[d] 如下:
full[d]=max{x∣A⊂{a[k]∣k∈[x,i]}}
也就是说此时集合 {a[k]∣k∈[full[d],i]} 包含了集合 A,并且此时 full[d] 取得是最靠右的值,考虑 a[i]≤d<n,首先考虑 d=a[i],假如 full[d]>last ,说明区间 [full[d],i] 之间已经包含 [0,d](也就是 [0,a[i]])所有元素,又由于 a[i] 唯一(只在下标 i 处出现过),因此区间 [full[d],i−1] 之间包含 [0,d−1] 之间所有元素,此时有:
mex(full[d],i)mex(full[d],i−1)mex(full[d],i)=d+1=d=mex(full[d],i−1)+1
也就是说 mex(full[d],i) 是在 mex(full[d],i−1) 的基础上累加了 1。再看 [k,i],k∈(last,full[d]),的情形,假如区间 [k,full[d]) 之间对应的元素仍在 [0,d] 范围内,则效果相同: mex(k,i)=mex(k,i−1)+1,而假如区间 [k,full[d]] 之间的元素有些不在 [0,d] 范围内,可知这些元素必定 >d,因此 mex(k,i)≥mex(k,i−1)+1,也可以先累加上一个 1,至于剩下的累加是在 d>a[i] 时考虑进去的。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 200010
using namespace std;
typedef long long ll;
int n,a[MAXN],pos[MAXN],full[MAXN],last;
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
while(scanf("%d",&n)&&n){
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(pos,0,sizeof(pos));
memset(full,0,sizeof(full));
ll tt=0,res=0;
for(int i=1;i<=n;i++){
if(a[i]<n){
last=pos[a[i]];
pos[a[i]]=i;
for(int d=a[i];d<n;d++){
if(d)full[d]=min(full[d-1],pos[d]);
else full[d]=i;
if(full[d]>last)tt+=full[d]-last;
else break;
}
}
res+=tt;
}
printf("%lld\n",res);
}
return 0;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200329111637474.png)