题意:给定一个序列,求其 所有连续子序列各元素和 的和(按空格断句),子序列中重复的元素只记一次。
方法:将问题分解,每次添加一个元素(设此元素为a),求此时序列中包含a的所有序列之和,(语文水平有限,举例说明)。
栗子:
dp 存储当前序列的所有子序列的和;
sum存储整个序列的和(即最终输出结果);
数组 weizhi 用来存放每个数字最终出现的的位置;
初始化dp = sum = 0(别忘了初始化数组a为零);
现有序列 1 2 3 4;
第一步 :1 dp += 1; sum += dp;
第二步 :1 2 dp += 2 + (1+2); sum += dp;
第三步 :1 2 3 dp += 3 + (3+2) + (3+2+1); sum += dp;
第四步 :1 2 3 4 dp += 4 + (4+3) + (4+3+2) + (4+3+2+1); sum += dp;
有没有看出规律呢?
每次新添加的元素加了几次?
在没有重复元素的前提下,第几步就加了几次;
但是有重复元素的话怎么办呢?
这时候我们创建的 weizhi(原谅我如此无耻的变量名)就有作用了:
设重复变量b,b之前最新出现的位置weizhi[b],那么weizhi[b]之前的序列就不需要加b了;
故此时b加的次数为 此时的步数 - weizhi[b];
所以这时候我们就可以解决这到题目了。
上代码
#include<cstdio>
#include<cstring>
using namespace std;
int op[1000001];
int main()
{
int T;
long long sum,dp;//注意会不会超int
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
memset(op,0,sizeof(op));
sum = 0;
dp = 0;
int a;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
dp = (i-op[a])*a + dp;
sum += dp;
op[a] = i;
}
printf("%lld\n",sum);
}
return 0;
}
水波!