标签:
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; }
标签:
原文地址:http://www.cnblogs.com/Emerald/p/4457788.html