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;

}

 

你可能感兴趣的:(array)