Zoj 3842 Beauty of Array

Problem地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5520

根据题目的要求,需要算出所有连续子数组的the beauty的总和。

那么要求这个这个总和,刚开始最容易想到的就是这样:

for( int i=1; i<=N; i++ ) {
    for( int j = 1; j<=i; j++ ) {
         ... //排除重复的数计算总和   
    }       
}

 这样子的结果实际上是 Time Limit Exceeded

因此采取这种方法是不当的,那么继续思考:

先思考没有重复的情况

例如:1,2 可以有子数组 1(1), 1,2(2),2(2),三个子数组,括号内为该子数组的beauty,

如果后面在加上一个3呢?可以得到子数组1(1), 1,2(2),2(2),1,2,3(6),2,3(5),3(3),可见增加了3个3,之所以是3个3。是因为这个3处在第三个位置。

同理,如果再增加一个数,形成数组列1,2,3,4,那么和1,2,3相比,其总和应该增加4个4

可以得出,没有重复的长度为n的数组,如果在第n+1个位置,再增加一个不重复的数x,则与没有重复的长度为n的数组的总beauty要增加x*(n+1)

 

既然得出了这一点,那么考虑存在重复的情况

在1,2,3,2,到第四个数,即2时,新增的序列为1,2,3,2   ,   2,3,2,  3,2,  2,但是和前一个3相比,以这个2为结尾的序列总beauty值增加了2*2,因为这个2与上一个2距离为2.

 

最后可以得出,每读进一个数,就可以根据前一个数算出以这个数为结尾的数列的beauty值。可以使默认每一个数的初始位置为0,之后进行更新。

最后计算总和就行了。

 

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int NUM_MAXN = 1000000 + 50; // the max number
long long value[ NUM_MAXN ]; // the sub ending with i position can totally get value[i] beauty
// Attention : long long
int pos[ NUM_MAXN ]; // the number i in the pos[i] position

int main() {
	int T;
	cin >> T;
	while( T -- ) {
		int N;
		scanf( "%d", &N );
		memset( pos, 0, sizeof(pos) );
		value[ 0 ] = 0;
		int tmp;
		for( int i=1; i<=N; i++ ) {
			scanf( "%d", &tmp );
			value[i] = value[ i-1 ] + ( i-pos[ tmp ] ) * tmp;
			pos[ tmp ] = i;
		}
		long long sum = 0;
		// Attention : long long
		for( int i=1; i<=N; i++ ) {
			sum = sum + value[ i ];
		}
		// Attention : long long
		printf( "%lld\n", sum );
	}
	return 0;
}

 

posted @ 2015-04-30 18:33  Emerald  阅读(482)  评论(0编辑  收藏  举报