hdu 4747(DP?线性递推)
Mex
Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 3876 Accepted Submission(s): 1290
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
Recommend
liuyiding
题意:给n个数,求所有区间内没有出现的最小非负整数和。
思路:有一个性质,对于mex(i,j),i固定,j增加,则mex(i,j)非严格递增。
记F[i]为以i结束的所有区间的值的和,则我们可以从F[i]推到F[i+1];记第i+1位的数位A[i+1],则我们只用考虑大于等于A[i+1]的数对F[i+1]=F[i]+?产生的影响(注意add的值,因为<A[I+1]-1的数不产生增量,A[I+1]-1的数之后会得到统计)
记S[i]表示0到i的所有数都出现的最小位置,如 数列 7 3 2 1 4 0 5 6 s[0]=6 s[1]=4 s[2]=3 s[3]=2 s[4]=2 s[5]=2 s[6]=2 s[7]=1 (倒着往前的)
如果j(j>=a[i+1])出现在1~i区间中,比较j最晚出现的位置与覆盖完全的1~j-1的最小位置的较小位置k,那么区间j的前一次出现的位置到k位置这个区间内所有点到i位置的值都+1。
为什么是j最晚出现的位置:例子是 8 8 8 6 7 3 2 1 4 0 5 6,做6的时候计算一下
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<string>
#include<map>
#include<queue>
#include<vector>
#include<stack>
#define ll long long
#define maxn 4001000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define rep(i,a,b) for(int i=a;i<=b;i++)
const ll P=1e9+7;
using namespace std;
map<int,int> p;
int n,a[201000],pre[201000],s[201000];
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
memset(pre,0,sizeof(pre));
memset(s,0,sizeof(s));
ll ans=0,add=0;
for(int i=1;i<=n;i++,ans+=add)
if(a[i]<=n)
{
int temp=pre[a[i]];
pre[a[i]]=i;
for(int j=a[i];j<=n;j++)
{
s[j]=j==0?pre[j]:min(s[j-1],pre[j]);
if(s[j]>temp) add+=s[j]-temp;
else break;
}
}
printf("%lld\n",ans);
}
}