题目大意:给定一个数组,求长度为x的字串中不同的数字的总数。
发现看别人的思路做的题写完之后等若干天之后还是想不懂怎么写。。。前几天一直在看后缀数组,ac自动机什么问题的,竟然将这题往后缀自动机那里想了。。。。然后发现实在是想不出来怎么写,然后发现了自己以前写的代码,然后就对自己真的无语了,周四就要去成都参加区域赛,这样的状态是真的让人很无语啊。。。
解题思路:
对于长度为i的字串得出的结果为ans[i],那么对于ans[i+1]等于每个长度i的字串后面加上一个数,然后减去数组的最后的一个长度为i的字串的值。对于数组可以先进行处理,ans[i+1]=ans[i]+cont[i]-pp[n-i+2],cont[i]代表对于一个数,其前面的与它自己相等的数的距离大于等于i的,pp数组记录的是后面将要处理的值,然后就可以了,
下面是代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<climits>
#include<map>
using namespace std;
#define rep(i,n) for(int i=0; i<n; i++)
#define repf(i,n,m) for(int i=(n); i<=(m); ++i)
#define repd(i,n,m) for(int i=(n); i>=(m); --i)
#define ll long long
#define arc(a) ((a)*(a))
#define inf 100000
#define exp 0.000001
#define N 1000006
int a[N];
ll ans[N];
int pre[N];
ll cont[N];
bool vis[N];
ll pp[N];
int n;
int main()
{
while(scanf("%d",&n) && n)
{
repf(i,1,n) scanf("%d",&a[i]);
memset(pre,-1,sizeof(pre));
memset(cont,0,sizeof(cont));
memset(vis,false,sizeof(vis));
memset(pp,0,sizeof(pp));
repf(i,1,n)
{
if(pre[a[i]]!=-1)
cont[i-pre[a[i]]]++;
else
cont[i]++;
pre[a[i]]=i;
}
repd(i,n-1,1) cont[i]+=cont[i+1];
pp[n+1]=0;
repd(i,n,1)
if(vis[a[i]]==false)
pp[i]=pp[i+1]+1,
vis[a[i]]=true;
else
pp[i]=pp[i+1];
ans[1]=n;
repf(i,2,n)
ans[i]=ans[i-1]+cont[i]-pp[n-i+2];
int m,x;
scanf("%d",&m);
while(m--)
{
scanf("%d",&x);
cout<<ans[x]<<endl;
}
}
return 0;
}