Skip to main content
Original252 words1 min

题解:P9421 [蓝桥杯 2023 国 B] 班级活动

Summary

每次修改一个元素,使序列中每个值恰好出现两次,求最小修改次数。统计每个值的出现次数:出现一次的记入 s1,出现超过两次的把多出的部分累加到 s2。多出的元素优先补给出现一次的值,若 s2 不小于 s1 则答案为 s2,否则还需把剩下的落单元素两两配对,答案为 s2 加上 s1 减 s2 与 0 取大后的一半。时间复杂度 O(n)。

题意简述​

每次修改 11 个元素,求序列中恰好每 22 个元素相同的最小操作次数。

解题思路​

对于每个元素 ii 的出现次数 aia_i,分类讨论:

  1. 如果 ai=2a_i=2,显然无需修改。
  2. 如果 ai=1a_i=1,可以直接修改其他元素,也可以把其他元素修改为 ii。
  3. 如果 ai>2a_i>2,修改多余的 ai−2a_i-2 个元素,且优先修改为其他 aj=1a_j=1 的元素。

具体实现:读入 tt,记录每个数出现的次数 aia_i,枚举所有的 aia_i:

{s1←s1+1ai=1s2←s2+(ai−2)ai>2\begin{cases} s_1\gets s_1+1 & a_i=1 \\ s_2\gets s_2+(a_i-2) & a_i>2 \end{cases}

对于 s1s_1 和 s2s_2,分类讨论:

  1. 如果 s2≥s1s_2\ge s_1,说明有足够 ai>2a_i>2 的元素可以给 ai=1a_i=1 的元素;
  2. 否则,还要修改 s1−s2s_1-s_2 个 ai=1a_i=1 的元素,每 22 个一组,要修改 s1−s22\frac{s_1-s_2}{2} 个元素。

综上,最终答案为:

s2+max⁡(s1−s2,0)2s_2+\frac{\max(s_1-s_2,0)}{2}

参考代码​

352 Bcpp
#include <bits/stdc++.h>
using namespace std;

const int N=100005;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
int t;
cin>>t;
a[t]++;
}
int s1=0,s2=0;
for(int i=1;i<=n;i++)
{
if(a[i]==1)s1+=1;
else if(a[i]>2)s2+=a[i]-2;
}
cout<<s2+max(s1-s2,0)/2<<'\n';
return 0;
}