zoj 3872 Beauty of Array

本文介绍了一种高效算法,用于求解一个数组中所有连续子数组内不同数字的总和。通过动态规划思想,文章详细解释了如何计算每个数字对最终结果的贡献,并附带实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

求一个数组的所有连续子串中不同的数字的和。

思路:

考虑每一个数字对于最终结果的贡献。

假设dp[i]表示以a[i]结尾的串的和,那么有dp[i] = dp[i-1] + a[i] * k。

这里的k,如果当前的a[i]没有在前面出现过,那么对结果的贡献肯定是k = i次,因为以它结尾的字串有i个;

但是如果出现过,假设它上一次出现的位置是pre,那么对结果的贡献就是k = i - pre喽。

考虑串 1 2 3 2 3,当我考虑最后一个3的时候,以它为结尾的子序列有:

1 2 3 2 3

2 3 2 3

3 2 3

2 3

3

显然前3个序列中有两个3,所以在前三个序列中,3的贡献已经被前面的3给计算了,所以只有后两个序列才能算当前的3的贡献。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <map>
 5 using namespace std;
 6 typedef long long ll;
 7 const int N = 1e5 + 10;
 8 int a[N];
 9 ll dp[N];
10 int main()
11 {
12     int t;
13     scanf("%d",&t);
14     while (t--)
15     {
16         memset(dp,0,sizeof(dp));
17         map<int,int> mp;
18         int n;
19         scanf("%d",&n);
20         for (int i = 1;i <= n;i++)
21         {
22             scanf("%d",&a[i]);
23         }
24         for (int i = 1;i <= n;i++)
25         {
26             dp[i] = dp[i-1] + (ll)(i-mp[a[i]]) * a[i];
27             mp[a[i]] = i;
28         }
29         ll ans = 0;
30         for (int i = 1;i <= n;i++) ans += dp[i];
31         printf("%lld\n",ans);
32     }
33     return 0;
34 }
35 /*
36 3
37 5
38 1 2 3 4 5
39 3
40 2 3 3
41 4
42 2 3 3 2
43 8*/

 

转载于:https://www.cnblogs.com/kickit/p/9000080.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值