题目链接: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; }