zoj-3872 Beauty of Array (dp)

]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 array A.

Input

There are multiple test cases. The first line of input contains an integer Tindicating 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 contains N positive integers separated by spaces. Every integer is no larger than 1000000.

<h4< dd="">Output

For each case, print the answer in one line.

<h4< dd="">Sample Input

3
5
1 2 3 4 5
3
2 3 3
4
2 3 3 2

<h4< dd="">Sample Outpu1021

38


这题题意的理解有一定难度,本人借鉴了一位大神的博客,得知大致的题意如下:
这个题的意思就是给n个数,求这n个数的子序列中不算重复的数的和。
比如第二个样例他的子序列就是{2},{2,3},{2,3,3},{3},{3,3},{3};
但每个子序列中重复的元素不被算入,所以他们的总和就是2+5+5+3+3+3=21;
但是这题的数据是1e5,用暴力肯定会超时,又因为每个子序列之间都有一定的递推关系,每个序列可以分解为无数个子序列。
依此,可以推断该题用dp写。
dp转移方程怎么推?用一个例子比较好解释,还用上面的例子给定4个数,分别是2 3 3 2,存入nu[Max]数组中,用dp[Max]记录子序列和(即前缀和)。
从第一个数往后推每一种可能性,则是:
                          2
                 3       3 2
          3     3 3     3 3 2
    2    2 3    2 3 3    2 3 3 2
   dp[1]  dp[2]   dp[3]     dp[4]

由上可知,dp[i]=dp[i-1]+nu[i]*i;
但该题要求去掉子序列中的重复元素,该怎么去呢?
我们继续利用上例的数据进行去重处理,可得:
                        2
               3       3 2
        3      3     3 2
  2    2 3    2 3     3 2
 dp[1]  dp[2]   dp[3]     dp[4]

如上,每一个序列中都没有重复的元素了
由上两图对比可知,可以想到用一个book[Max*10]数组记录每一个元素最后出现的位置,把nu[i]*i改成nu[i]*(i-book[nu[i]])
即转移方程改为:dp[i]=dp[i-1]+nu[i]*(i-book[nu[i]]);然后把dp[n]中的值相加即可;

这题还有个坑点,对dp[n]求和会爆int,应用long long;

代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int M = 111111;
long long book[M*10],dp[M],nu[M];
int main(){
	int t;
	cin>>t;
	while(t--){
		long long ans=0;
		memset(book,0,sizeof(book));
		memset(dp,0,sizeof(dp));
		int n;
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>nu[i];
			
		}
		for(int i=1;i<=n;i++){
			dp[i]=dp[i-1]+nu[i]*(i-book[nu[i]]);
			book[nu[i]]=i;
			ans+=dp[i];	
		}
		cout<<ans<<endl;
	}
	return 0;
}

参考博客:http://blog.csdn.net/zhao5502169/article/details/70037098  





原文地址:https://www.cnblogs.com/zmin/p/7281981.html