HDU 4455 Substrings
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4455
令
dp[w]
为
w
对应的答案。
则对于dp[w+1]
细想:对于以第
i
个元素A[i] 开始的长度为
w
的子段。
长度扩张到w+1 时,包含进入了
A[w+i]
如果此时 [w,w+i−1] 中没有 A[i] 。 A[i] 产生1的贡献.
因为子段长度的扩张。最后一个子段作废。所以要减去。
对于新产生的贡献。根据前面的分析。:
即为:
i−p[i]>w,满足此条件的所有i的数量。
p[i] 为上一个出现 A[i] 的下标。
#include <algorithm>
#include <stdio.h>
#include <string.h>
#define MAXN 1000006
using namespace std;
typedef long long LL;
LL dp[MAXN];
int A[MAXN];
int B[MAXN];
int C[MAXN];
int D[MAXN];
int main ()
{
int n;
while(scanf("%d",&n)==1&&n)
{
memset(B,0,sizeof B);
memset(D,0,sizeof D);
for(int i=1;i<=n;i++) scanf("%d",A+i);
for(int i=1;i<=n;i++)
{
B[i-D[A[i]]]++;
D[A[i]]=i;
}
for(int i=n;i;i--) B[i]+=B[i+1];
memset(D,0,sizeof D);
for(int i=n,res=0;i;i--)
{
if(D[A[i]]==0)res++;
D[A[i]]++;
C[n-i+1]=res;
}
dp[1]=n;
for(int i=2;i<=n;i++) dp[i]=dp[i-1]-(LL)C[i-1]+(LL)B[i];
int Q,a;
scanf("%d",&Q);
while(Q--)
{
scanf("%d",&a);
printf("%lld\n",dp[a]);
}
}
return 0;
}