C-数颜色
题意
给出  个数,这 
 个数***有 
 个区间,对于每个区间求不同数字的个数,把所有区间的个数加起来,就得到了 
 。
分析
看了看数据,好像打表就行了。
我们怎么能暴力?
我要介绍的东西,叫前缀和。
什么是前缀和
- 前缀和可以简单理解为数列的前 项的和( ) 
- 
前缀和是指给定一个数组,计算出一个新的数组,其中每个元素是原数组中该位置及其之前所有元素的和。 
- 
具体计算方法如下: 
- 初始化一个新数组prefix_sum,长度与原数组相同。
- 将原数组的第一个元素复制到prefix_sum的第一个位置。
- 从第二个位置开始遍历原数组,依次计算prefix_sum[i] = prefix_sum[i-1] + 原数组[i]。
- 返回新数组prefix_sum作为结果。
- 
例如,对于原数组[1, 2, 3, 4, 5],计算出的前缀和数组为[1, 3, 6, 10, 15]。 
- 
前缀和的应用场景很多,例如可以用于高效计算数组中某个区间内元素的和。 
(  
 )
- 自行总结 :一个预处理的过程,在输入时便把前面的数据(和,差,积等)算出来。
为什么本题能用前缀和
我们不难发现:在从  到 
 这个区间中,设有 
 个不同的数,如果数组中第 
 项不包含在这个区间中,则在第 
 到 
 ***有 
 个不同的数,否则这个区间中还是只有 
  个数。
代码实现时的困难
- 
:如果你认真看完了上一个标题,那么不禁会问:怎么前缀和? 
- 
:使用一个二维数组 存储自 到 这个区间中不同的数的个数,从1到 读入 接着从1枚举 至 ,再用上一个标题下的方法前缀和预处理。 
- 
:如何记录从 到 这个区间中不同数的个数? 
- 
:用一个二维数组 记录在 后一个数是否存在。 
什么,你还想要代码?
#include <bits/stdc++.h>
using namespace std;
const int N=1e6;
long long n,cnt;
long long a[N];
map<long long,map<long long,long long> > check;
map<long long,map<long long,long long> > sum;
//运用map防止数组爆炸 
//check为记录一个数是否存在 
//sum用于i~j的前缀和 
int main(){
	cin>>n;
	for(long long i=1;i<=n;i++){
		cin>>a[i];
		for(long long j=1;j<=i;j++){
			if(check[j][a[i]]==0){
				check[j][a[i]]=1;
				sum[j][i]=sum[j][i-1]+1;
			}
			else sum[j][i]=sum[j][i-1];
		}
	}
	//前缀和预处理 
	for(long long i=1;i<=n;i++){
		for(long long j=i;j<=n;j++){
			cnt+=sum[i][j];
		}
	}
	//把所有预处理的sum加起来 
	cout<<cnt;
	return 0;
}

 京公网安备 11010502036488号
京公网安备 11010502036488号