题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4455
题目大意:
给定一个长为n(n<=10^6)的数组,数组中的数大于0小于10^6
询问q次,询问长度为w的子数组(连续的)的权值和,子数组的权值为其数组中的不同元素的个数.
题目思路:
拿样例写一下
1: {1} , {1} , {2} , {3} , {4} , {4} , {5}
2: {1,1} , {1,2} , {2,3} , {3,4} , {4,4} , {4,5}
3: {1,1,2} , {1,2,3} , {2,3,4} , {3,4,4} , {4,4,5}
4: {1,1,2,3} , {1,2,3,4} , {2,3,4,4} , {3,4,4,5}
...
容易发现可以得出一个发现:
长度为w的值肯定包含长度为w-1的值减去最后一个字数组的权值和
例:
2: {1,1} , {1,2} , {2,3} , {3,4} , {4,4} , {4,5}
3: {1,1,2} , {1,2,3} , {2,3,4} , {3,4,4} , {4,4,5}
dp[3 ] = dp[2] - 权值[{4,5}] + ?而'?'就表示添加上那些标蓝色的数之后要添加的值.
设某个标蓝色的数为a[i],另外一个和它相等的且和它最近的数为a[j],且i>j
如果i-j>w的话那么添上这个标蓝的数就可以使得dp[w]+1
所以我们只要求出cnt[dis]即可,dis既某数离在它之前且相等的且和它最近的数的距离.
代码:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define ls rt<<1
#define rs ls|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define middle (l+r)>>1
#define eps (1e-9)
#define type int
#define clr_all(x,c) memset(x,c,sizeof(x))
#define clr(x,c,n) memset(x,c,sizeof(x[0])*(n+1))
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define pi acos(-1.0)
#define _max(x,y) (((x)>(y))? (x):(y))
#define _min(x,y) (((x)<(y))? (x):(y))
#define _abs(x) ((x)<0? (-(x)):(x))
#define getmin(x,y) (x= (x==-1 || (y)<x)? (y):x)
#define getmax(x,y) (x= ((y)>x)? (y):x)
template <class T> void _swap(T &x,T &y){T t=x;x=y;y=t;}
int TS,cas=1;
const int M=1000000+5;
int n,q,w;
ll dp[M];
int dp1[M],dp2[M],a[M];
void run(){
int i,j;
clr(dp,0,n),clr(dp1,0,n),clr(dp2,0,n);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
dp1[i-dp[a[i]]]++;
dp[a[i]]=i;
}
clr(dp,0,n),dp[a[n]]=1,dp2[1]=1;
for(i=n-1,j=2;i>=1;i--,j++){
if(dp[a[i]]) dp2[j]=dp2[j-1];
else dp2[j]=dp2[j-1]+1,dp[a[i]]=1;
}
clr(dp,0,n),dp[1]=n,j=n;
for(i=2;i<=n;i++){
dp[i]=dp[i-1]-ll(dp2[i-1]);
j-=dp1[i-1];
dp[i]+=ll(j);
}
scanf("%d",&q);
while(q--){
scanf("%d",&w);
printf("%I64d\n",dp[w]);
}
}
void preSof(){
}
int main(){
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
preSof();
//run();
while(~scanf("%d",&n) && n) run();
//for(scanf("%d",&TS);cas<=TS;cas++) run();
return 0;
}