题解归档 - cf1198A
本文最后由方少年更新于2026 年 6 月 28 日,已超过0天没有更新。如果文章内容或图片资源失效,请留言反馈,将会及时处理,谢谢!
题解归档 - cf1198A
本文由 cf-code 本地题解库自动归档;公开内容以本地 AC/验证版本为准。
- 本地编号:
cf1198A - 本地来源:
problems/cf1198A/idea.md - 题目链接:https://codeforces.com/contest/1198/problem/A
- 原始标题:CF1198A — MP3
思路
CF1198A — MP3
题意
给定长度 n 的整数数组,选 l ≤ r,把 < l 的改成 l、把 > r 的改成 r。压缩后不同值个数为 K,每个值需 k = ⌈log₂ K⌉ 位,总位数 nk 不能超过 I 字节(8I 位)。求最少修改元素个数。
关键观察
- 排序后,最优
l、r一定取排序数组中某段连续下标[i, j]对应的a[i]与a[j]:保留区间内原值,左侧全压到l=a[i],右侧全压到r=a[j]。 - 压到
l/r不会产生新的不同值(l、r已在区间内出现)。 - 修改数 =
(i-1) + (n-j)(1-based)。 - 约束:
n · ⌈log₂ K⌉ ≤ 8I,其中K为区间[i,j]内不同值个数。
算法
双指针滑动窗口:
- 维护窗口
[i, j]的不同值个数zc。 - 对每个左端
i,尽量右扩j;若n·kbit(zc) > 8I则停止扩张。 - 在合法窗口上更新
ans = min(ans, i-1+n-j)。 kbit(K)用K≤1 → 0,否则64-__builtin_clzll(K-1)即⌈log₂ K⌉。
复杂度 O(n log n) 排序 + O(n) 双指针。
验证
- 样例通过。
- Kali 本地对拍 500 组(
gen+brutevssolution)全部一致。
结论
经典双指针 + 不同值计数;Div.1 A 题。
代码
来源:problems/cf1198A/solution.cpp
/* Author: likely
* Time: 2026-06-08 03:16:28
**/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=4e5+5;
ll s[maxn],n,I,i,j,ans,zc;
map<ll,ll>mp;
ll kbit(ll K){
if(K<=1) return 0;
return 64-__builtin_clzll(K-1);
}
int main(){
cin>>n>>I;
for(i=1;i<=n;i++) cin>>s[i];
sort(s+1,s+n+1);
ans=n;
j=1;
zc=0;
for(i=1;i<=n;i++){
if(j<i) j=i;
while(j<=n){
if(mp[s[j]]==0) zc++;
mp[s[j]]++;
if(n*kbit(zc)<=8*I){
ans=min(ans,i-1+n-j);
j++;
}else{
mp[s[j]]--;
if(mp[s[j]]==0) zc--;
break;
}
}
if(mp[s[i]]){
mp[s[i]]--;
if(mp[s[i]]==0) zc--;
}
}
cout<<ans<<"\n";
return 0;
}
~ ~ The End ~ ~
文章标题:题解归档 - cf1198A
文章链接:https://www.fangshaonian.cn/archives/182/
最后编辑:2026 年 6 月 28 日 19:03 By 方少年
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)