题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=4455
题目大意给你一串有序数,分成m个子集后,每个子集中不同元素的个数和是多少
这题感谢帽神的提点,不然真想不到可以这样dp
用样例为例子 1 1 2 3 4 4 5
很容易知道dp[1]=7;
当m=2时 可以分为 1 1,1 2,2 3,3 4,4 4,4 5;
这时可以发现,当m++时每个子集加入了后面一个数,最后一个子集被删去了
可以得到dp[i]=dp[i-1]-最后子集不重复元素个数+新增加的不同元素的个数。
后面两个都可以得出于是求证。
答案要用longlong。这里wa了几次~~
#include<stdio.h>
#include<string.h>
#define MAX 1000010
int equ[MAX]; //记录距离为i的相同的数有多少个
int dis[MAX]; //记录一个数离上一个相同的数的距离
int a[MAX];
int vis[MAX]; //记录后面哪些数出现过
int f[MAX];
long long ans[MAX];
int main()
{
int n;
while(scanf("%d",&n)==1&&n)
{
int i;
memset(dis,0,sizeof(dis));
memset(equ,0,sizeof(equ));
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
equ[i-dis[a[i]]]++;
dis[a[i]]=i;
}
memset(vis,0,sizeof(vis));
f[1]=1;
vis[a[n]]=1;
for(i=2;i<=n;i++)
{
if(!vis[a[n-i+1]])
{
vis[a[n-i+1]]=1;
f[i]=f[i-1]+1;
}
else
f[i]=f[i-1];
}
ans[1]=n;
long long tt=n;
for(i=2;i<=n;i++)
{
ans[i]=ans[i-1]-f[i-1];
tt-=equ[i-1];
ans[i]+=tt;
}
int m;
scanf("%d",&m);
for(i=0;i<m;i++)
{
int b;
scanf("%d",&b);
printf("%lld\n",ans[b]);
}
}
}