牛客周赛Round64-C题题解

牛客周赛Round64-C题题解

题目描述:

小红拿到了一个数组,她有若干次询问,每次询问一个前缀内有多少对相同的数。你能帮帮她吗?

​ 如果存在i,j,1<=i<j<=n,且ai=aj,那么 (ai,aj) 就是一对相同的数对。只要下标不同,就是不同的数对。

输入描述:

第一行输入一个正整数n,代表数组大小。
第二行输入n个正整数ai,代表小红拿到的数组。
1<=n<=10^5
1≤ai≤10^9

输出描述:

输出n个整数,第i个整数代表前缀[1,i]内有多少对相同的数。

示例1

输入:

6
2 3 3 3 1 2

输出:

0 0 1 3 3 4

说明:

对于前缀 [2],没有相同的数。
对于前缀 [2,3],没有相同的数。
对于前缀 [2,3,3],有1对相同的数。
对于前缀 [2,3,3,3],有3对相同的数。
对于前缀 [2,3,3,3,1],有3对相同的数。
对于前缀 [2,3,3,3,1,2],有4对相同的数。

解题思路:

对于这个题,我们可以首先思考一下暴力做法,

我们可以套两层循环,外层循环遍历[1,n]第二层循环遍历[1,i),

也就是我们可以把[1,i)区间内与a[i]相等的数用一个数组统计一下。

时间复杂度O(n^2)

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n;
int a[N],q[N];
int main()
{
	cin>>n;
	
	for(int i=1;i<=n;i++) cin>>a[i];
	
	for(int i=1;i<=n;i++)
	{
	     for(int j=1;j<i;j++)
	     {
	     	 if(a[i]==a[j]) q[i]++; 
		 }
		 
		    q[i]+=q[i-1];
	}
	
	
	
	for(int i=1;i<=n;i++) cout<<q[i]<<" ";
	
	
	
	return 0;
}


这个代码只能过20%的测试用例,那我们来思考一下能不能优化一下这个算法。

实际上,我们不需要再遍历[1,i)区间,我们只需要遍历[1,n]区间就足够了,我们可以用STL中的map来记录数的出现次数.

AC代码如下:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e5+10;
int n;
void solve()
{
	 cin>>n;
	 map<int,int>mp;
	 
	 ll ans=0;
	 
	 for(int i=1;i<=n;i++)
	 {
	 	int x;
	 	cin>>x;
	 	ans+=mp[x];
//	 	cout<<mp[x]<<" ";
	 	mp[x]++;
	 	
	 	cout<<ans<<" ";
	 }
	 
}
int main()
{
	solve();
	
	return 0;
}
posted @ 2024-10-28 21:32  Emila  阅读(20)  评论(0)    收藏  举报