Beauty of Array问题, 贡献度问题

每次求的是这个数对于整体的贡献度:
例子:
1 2 1 3
for 1 : n
ans = 0
i = 1:
定义一个book数组(int)记录每一个的下表, 因为以后是要用的!!!!!!!!
现在讨论第一个1的贡献度:
1
1 2
1 2 1
1 2 1 3
第一个1的贡献度是四次, 那么1在哪里贡献了呢, 那只有是包含1的, 就是含有1之前的所有都是有所贡献的, ans += (4) * (1) ;
4 是指1贡献的次数, 1是指1之前且包含1的个数是1个。
现在i = 2:
现在讨论2的贡献度:
2
2 1
2 1 3
2总共贡献了三次, 那么2之前且包含2的个数有几个呢, 有从第一个1开始的包含2, 有从2开始的包含2, 那么, 包含2的个数总共有2个。则ans += (3) * (2), // ans += (n - i + 1) * (i);
现在i = 3:
现在讨论第二个1的贡献度:
1
1 3
此时第二个1贡献了2次, 那么之前且包含第二个1的有几个呢?有从第一个1开始的包含, 有从2开始的包含, 有从第二个1开始的包含,但是此时题目要求是每个子串不同的个数, 所以在第一个1(包含)之前的都没有贡献到, 因为第一个1已经把他前面的贡献了, 再有第二个1的话就没有贡献了, 所以此时要把前面没有贡献的个数减掉:
即:ans += (2) * (3 - 1) // ans += (n - i + 1) * (i - index[1]), index[1]表示第一个1的下标, 也是第二个1没有贡献的个数。
i = 4
现在 ans += (1) * (4) // ans += (n - i + 1) * (i)

最下面有蓝桥杯的题目, 可以说是原题吧

链接:https://ac.nowcoder.com/acm/contest/8409/B
来源:牛客网

Gromah and LZR have entered the second level. There is a sequence a1. a2. a3…an on the wall.

There is also a note board saying “the beauty value of a sequence is the number of different elements in the sequence”.

LZR soon comes up with the password of this level, which is the sum of the beauty values of all successive subintervals of the sequence on the wall.

Please help them determine the password!
链接:https://ac.nowcoder.com/acm/contest/8409/B
来源:牛客网

The first line contains one positive integer n_{}n

, denoting the length of the sequence.

The second line contains n_{}n

positive integers a1, a2, a3…an
, denoting the sequence.
链接:https://ac.nowcoder.com/acm/contest/8409/B
来源:牛客网

Print a non-negative integer in a single line, denoting the answer.
4
1 2 1 3

来自:https://blog.csdn.net/qq_42936517/article/details/84620256

Beauty of Array

Edward has an array A with N integers. He defines the beauty of an array as the summation of all distinct integers in the array. Now Edward wants to know the summation of the beauty of all contiguous subarray of the array A.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains an integer N (1 <= N <= 100000), which indicates the size of the array. The next line contains N positive integers separated by spaces. Every integer is no larger than 1000000.
Output

For each case, print the answer in one line.

Sample Input
3
5
1 2 3 4 5
3
2 3 3
4
2 3 3 2

Sample Output
105
21
38

题意:给出n个数字的序列,求所有连续的子序列中不同数字的和的和
例:2 3 3

连续的子序列 该子序列不同数字的和
2 2
2 3 5
2 3 3 5
3 3
3 3 3
3 3
最终结果 2+5+5+3+3+3=21

思路:找每个数对最终结果的贡献
包含a[i]的连续子序列有:
1.如果a[i]之前没出现过,就有(n-i)(i+1)个
2.如果a[i]之前出现过了,就有(n-i)
((i+1)-(vis[a[i]]+1))个
注:数组下标从0开始的

以下分析暂假设a[i]之前没出现过
子序列中要想有a[i]及a[i]之后的元素,一定会有a[i],也就是说对于a[i]及a[i]之前的每一个元素,都会用到(n-i)个a[i],从第一个元素的到a[i]一共有(i+1)个元素,
所以a[i]对最终结果的贡献就是 a[i](n-i)(i+1)

现在考虑a[i]之前出现过
对于a[i]上次出现的位置到a[i]现在的位置之间的元素,包含a[i]现在的位置,都会用到(n-i)个a[i],而 (vis[a[i]],i] 是((i+1)-(vis[a[i]]+1))个,
所以所以a[i]对最终结果的贡献就是 a[i](n-i)((i+1)-(vis[a[i]]+1))

乘号显示不出来,具体看代码吧

#include<cstdio>
#include<cstring>
using namespace std; 
typedef long long ll;
const int maxn=1e5+5;
ll a[maxn];
int vis[maxn];//这个元素最后出现的位置,如果是-1就是还没出现过
int main(){
      
      
	int T,n;
	scanf("%d",&T);
	while(T--){
      
      
		scanf("%d",&n);
		memset(vis,-1,sizeof(vis));
		for(int i=0;i<n;i++)
		scanf("%lld",&a[i]);
		ll sum=0;
		for(int i=0;i<n;i++){
      
      
			if(vis[a[i]]!=-1){
      
        //a[i]在前面出现过了 
				sum+=a[i]*(n-i)*(i-vis[a[i]]);
				//也就是sum+=a[i]*(n-i)*((i+1)-(vis[a[i]]+1)) 
			}
			else{
      
       //a[i]之前没出现过
				sum+=a[i]*(n-i)*(i+1);
			}
			vis[a[i]]=i;//更新a[i]最后出现的位置 
		}
		printf("%lld\n",sum); 
	}
	return 0;
} 

   
    
    
   
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

蓝桥杯:
H 子串分值

【问题描述】

对于一个字符串 S,我们定义 S 的分值 f (S ) 为 S 中出现的不同的字符个
数。例如 f (”aba”) = 2, f (”abc”) = 3, f (”aaa”) = 1。
现在给定一个字符串 S [0::n − 1](长度为 n),请你计算对于所有 S 的非空
子串 S [i:: j](0 ≤ i ≤ j < n), f (S [i:: j]) 的和是多少。
输入一行包含一个由小写字母组成的字符串S。
ababc
【样例输出】

28

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
int main()
{
    
    
    char s[100005];
    scanf("%s", s + 1);
    int len = strlen(s + 1);
    int book[100005] = {
    
    0};
    ll ans = 0;
    for (int i = 1; i <= len; i++)
    {
    
    
        if (book[(int)s[i]])
            ans += (len - i + 1) * (i - book[(int)s[i]]);
        else
            ans += (len - i + 1) * i;
        book[(int)s[i]] = i;
    }
    cout << ans << endl;
    return 0;
}

Beauty of Array

Edward has an array A with N integers. He defines the beauty of an array as the summation of all distinct integers in the array. Now Edward wants to know the summation of the beauty of all contiguous subarray of the array A.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains an integer N (1 <= N <= 100000), which indicates the size of the array. The next line contains N positive integers separated by spaces. Every integer is no larger than 1000000.
Output

For each case, print the answer in one line.

Sample Input
3
5
1 2 3 4 5
3
2 3 3
4
2 3 3 2

Sample Output
105
21
38

题意:给出n个数字的序列,求所有连续的子序列中不同数字的和的和
例:2 3 3

连续的子序列 该子序列不同数字的和
2 2
2 3 5
2 3 3 5
3 3
3 3 3
3 3
最终结果 2+5+5+3+3+3=21

思路:找每个数对最终结果的贡献
包含a[i]的连续子序列有:
1.如果a[i]之前没出现过,就有(n-i)(i+1)个
2.如果a[i]之前出现过了,就有(n-i)
((i+1)-(vis[a[i]]+1))个
注:数组下标从0开始的

以下分析暂假设a[i]之前没出现过
子序列中要想有a[i]及a[i]之后的元素,一定会有a[i],也就是说对于a[i]及a[i]之前的每一个元素,都会用到(n-i)个a[i],从第一个元素的到a[i]一共有(i+1)个元素,
所以a[i]对最终结果的贡献就是 a[i](n-i)(i+1)

现在考虑a[i]之前出现过
对于a[i]上次出现的位置到a[i]现在的位置之间的元素,包含a[i]现在的位置,都会用到(n-i)个a[i],而 (vis[a[i]],i] 是((i+1)-(vis[a[i]]+1))个,
所以所以a[i]对最终结果的贡献就是 a[i](n-i)((i+1)-(vis[a[i]]+1))

乘号显示不出来,具体看代码吧

#include<cstdio>
#include<cstring>
using namespace std; 
typedef long long ll;
const int maxn=1e5+5;
ll a[maxn];
int vis[maxn];//这个元素最后出现的位置,如果是-1就是还没出现过
int main(){
    
    
	int T,n;
	scanf("%d",&T);
	while(T--){
    
    
		scanf("%d",&n);
		memset(vis,-1,sizeof(vis));
		for(int i=0;i<n;i++)
		scanf("%lld",&a[i]);
		ll sum=0;
		for(int i=0;i<n;i++){
    
    
			if(vis[a[i]]!=-1){
    
      //a[i]在前面出现过了 
				sum+=a[i]*(n-i)*(i-vis[a[i]]);
				//也就是sum+=a[i]*(n-i)*((i+1)-(vis[a[i]]+1)) 
			}
			else{
    
     //a[i]之前没出现过
				sum+=a[i]*(n-i)*(i+1);
			}
			vis[a[i]]=i;//更新a[i]最后出现的位置 
		}
		printf("%lld\n",sum); 
	}
	return 0;
} 

   
  
  
   
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

おすすめ

転載: blog.csdn.net/YingShen_xyz/article/details/109265146