题意
大小为
n
n
n 的数组,
K
K
K 个不同值,需要
k
=
c
e
i
l
(
l
o
g
2
K
)
k=ceil(log2K)
k=ceil(log2K) 位存储每个值,整个数组需要
n
k
nk
nk 位存储,
现在需要压缩到
8
∗
I
8*I
8∗I ,求需要改变的数的最小值。
思路
首先题目关注的是不同的值以及每一个值相对应的个数,先存入
m
a
p
map
map 处理
正向求解的话需要枚举每个符合条件的区间,比较麻烦,
逆向求解则只需求出
k
k
k 的最大值,然后维护一个大小为
k
k
k 的滑动窗口,不断更新答案即可。
代码实现
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <vector>
#include <climits>
using namespace std;
typedef long long ll;
const int maxn=400010;
int n,I,k,K,a[maxn];
map<int,int> mp;
vector<int> b;
int main()
{
scanf("%d%d",&n,&I);
I=8*I;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
mp[a[i]]++;
}
for(map<int,int>::iterator it=mp.begin();
it!=mp.end();it++){
b.push_back(it->first);
}
int ans=INT_MAX;
if(n*ceil(log2(mp.size()))<=I){
printf("0\n");
return 0;
}
k=min(1<<(I/n),n);
int sum=0,sz=mp.size();
for(int i=0;i<k;i++){
sum+=mp[b[i]];
}
ans=min(ans,n-sum);
for(int i=k;i<sz;i++){
sum-=mp[b[i-k]];
sum+=mp[b[i]];
ans=min(ans,n-sum);
}
printf("%d\n",ans);
return 0;
}