hdu 4455 dp

题目大意:给定一个数组,求长度为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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

#define rep(i,n) for(int i=0; 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<


你可能感兴趣的:(hdu 4455 dp)