题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4455
题意:给出长度为n个字符串,然后Q个询问,问长度为k的每个子串中不同的数字个数之和是多少
思路:思路很难想,状态转移:dp[i]=dp[i-1]-A+B,其中A是最后一个长度为i-1的区间的不同数的个数,B是距离上一个与其相等的数为i的数的个数
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 1000010;
int a[maxn], last[maxn], fl[maxn];
int pre[maxn], fin[maxn], s[maxn];
long long dp[maxn];
/* pre[i]表示a[i]在前面出现过的距离最近的位置
fin[i]表示最后i个数所含元素不同的个数
s[i]表示离上一个相等元素距离为i的个数 */
int main()
{
int n;
while(~scanf("%d", &n) && n)
{
memset(pre, 0, sizeof(pre));
memset(s, 0, sizeof(s));
memset(last, 0, sizeof(last));
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
s[i - pre[a[i]]]++;
pre[a[i]] = i;
}
memset(fl, 0, sizeof(fl));
fin[1] = 1;
fl[a[n]] = 1;
for(int i = 2; i <= n; i++)
{
if(fl[a[n - i + 1]] == 0)
{
fl[a[n - i + 1]] = 1;
fin[i] = fin[i - 1] + 1;
}
else
fin[i] = fin[i - 1];
}
dp[1] = n;
int sum = n;
for(int i = 2; i <= n; i++)
{
dp[i] = dp[i - 1] - fin[i - 1];
sum -= s[i - 1];
dp[i] += sum;
}
int m;
scanf("%d", &m);
while(m--)
{
int t;
scanf("%d", &t);
printf("%I64d\n", dp[t]);
}
}
return 0;
}