dp。dp[ i ]表示长度为 i 的答案。则我们可以发现有dp[ i ] 和 dp[ i - 1 ],我们看各自的第一种满足的情况有{a1,a2,a3.......ai}, {a1,a2,a3.......a[i - 1]}则可以发现dp[ i ],和dp[i - 1]是存在递推关系的。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int N = 1000100;
int l[N], add[N], a[N], sub[N], cnt[N], n;LL dp[N];
bool vis[N];
void slove()
{
int i, j;
sub[n + 1] = 0;CLR(vis, 0);
for(i = n; i > 0; i --)
{
if(!vis[a[i]]) sub[i] = sub[i + 1] + 1, vis[a[i]] = 1;
else sub[i] = sub[i + 1];
}//sub数组表示从后往前数出现数字的个数。
CLR(l, 0);CLR(add, 0);cnt[0] = 0;
for(i = 1; i <= n; i ++)//l数组表示数字i前一次出现的位置
{
if(l[a[i]])add[i - l[a[i]]] ++, cnt[i] = cnt[i - 1] + 1;
else cnt[i] = cnt[i - 1];
l[a[i]] = i;
}//cnt表示当前位置为止出现的相同元素的数对个数。
dp[1] = n;
for(i = 1; i <= n; i ++) add[i] += add[i - 1];//add[len]数组表示ai = aj且j-i <= len + 1的数对个数。
for(i = 2; i <= n; i ++)
{
dp[i] = dp[i - 1] + (n - i + 1 - add[i - 1]) - sub[n - i + 2] + cnt[i - 1];
}
}
int main()
{
//freopen("input.txt", "r", stdin);
int i, j, q, w;
while(scanf("%d", &n), n)
{
for(i = 1; i <= n; i ++)
{
scanf("%d", &a[i]);
}
slove();
scanf("%d", &q);
while(q --)
{
scanf("%d", &w);
printf("%I64d\n", dp[w]);
}
}
}