牛客周赛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;
}

浙公网安备 33010602011771号