ZOJ 3872 Beauty of Array 动态规划子序列

来源:互联网 发布:银行 知乎 编辑:程序博客网 时间:2024/06/03 21:54

题目地址:点击打开链接

Beauty of Array

Time Limit: 2 Seconds      Memory Limit: 65536 KB

Edward has an array A with N integers. He defines the beauty of an array as the summation of all distinct integers in the array. Now Edward wants to know the summation of the beauty of all contiguous subarray of the arrayA.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains an integer N (1 <= N <= 100000), which indicates the size of the array. The next line containsN positive integers separated by spaces. Every integer is no larger than 1000000.

Output

For each case, print the answer in one line.

Sample Input

351 2 3 4 532 3 342 3 3 2

Sample Output

1052138

题意: 给出一个数列,求出所有的连续子序列之和。即每一个连续子序列之和的和。

示例:2, 3, 3. 他有6个连续子序列:



每一个子序列中的重复元素只加一次,看做这个子序列的和,最后把这6个子序列的和再加起来,就是答案。


用暴力做法超时。下面用dp动态规划。


先看一个例子:1   2    3     2 

我们用一个变量dp来记录以每个元素结尾的子序列的漂亮和,如图,dp表示每一列的和。

这是一个递推的过程,可以用前面的出来的dp值,推出新加入一个元素的dp值

最后把这些dp的值加起来即可。


还有一个问题,重复的数。用一个数组pre记录每一个数字出现的位置。看着上面的图,假设我们现在前三个数的子序列都算完了,现在把第4个数字2加进去(竖着看),以2结尾的子序列会有四个,其中包含上一个2的子序列是前两个,有没有发现规律。包含上一个2的子序列都是和现在加进去的2重复了一个2,减掉几个2呢,就是上一个2出现的位置到第一位置,这一串都有重复,即pre[a]个。所以dp=dp + i*a - pre[a]*a;


代码:

#include<stdio.h>#include<string.h>long long T,n,a,dp,sum;int pre[1000010];//pre[a]记录数字 a 上一次出现的位置 int main(){scanf("%lld",&T);while(T--){scanf("%lld",&n);memset(pre,0,sizeof(pre));sum=0;dp=0;for(int i=1;i<=n;i++){scanf("%lld",&a);dp+=i*a - pre[a]*a;//以a结尾的子序列的漂亮和sum+=dp;pre[a]=i;//记下数字a出现的位置}printf("%lld\n",sum);}return 0; } 



0 0
原创粉丝点击