hdu 4455 Substrings

题目链接: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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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)
template  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;
}


你可能感兴趣的:(dp)