Codeforces Round #576 (Div. 2)
One common way of digitalizing sound is to record sound intensity at particular time moments. For each time moment intensity is recorded as a non-negative integer. Thus we can represent a sound file as an array of n non-negative integers.
If there are exactly K distinct values in the array, then we need k=⌈log2K⌉ bits to store each value. It then takes nk bits to store the whole file.
To reduce the memory consumption we need to apply some compression. One common way is to reduce the number of possible intensity values. We choose two integers l≤r, and after that all intensity values are changed in the following way: if the intensity value is within the range [l;r], we don't change it. If it is less than l, we change it to l; if it is greater than r, we change it to r. You can see that we lose some low and some high intensities.
Your task is to apply this compression in such a way that the file fits onto a disk of size I bytes, and the number of changed elements in the array is minimal possible.
We remind you that 1 byte contains 8 bits.
k=⌈log2K⌉ is the smallest integer such that K≤2k. In particular, if K=1, then k=0.
Input
The first line contains two integers n and I (1≤n≤4⋅105, 1≤I≤108) — the length of the array and the size of the disk in bytes, respectively.
The next line contains n integers ai (0≤ai≤109) — the array denoting the sound file.
Output
Print a single integer — the minimal possible number of changed elements.
Examples
input
6 1
2 1 2 3 4 3
output
2
input
6 2
2 1 2 3 4 3
output
0
input
6 1
1 1 2 2 3 3
output
2
Note
In the first example we can choose l=2,r=3. The array becomes 2 2 2 3 3 3, the number of distinct elements is K=2, and the sound file fits onto the disk. Only two values are changed.
In the second example the disk is larger, so the initial file fits it and no changes are required.
In the third example we have to change both 1s or both 3s.
题意:比赛的时候半天没看懂题,可能是我太菜了orzorz,这题意思就是给你n个数字,
它占用的空间为 n*[log2(k)] ,其中k为不同数字的个数,如 1,2,2,3 有三个不同数字。
然后还给你个I值,能存储的总空间为8*I,问你把这n个数字放入总空间最少要改多少个数字。
思路:先根据I值算出最大能放下的不同数字个数,在用尺取法找一遍最优解,
注意有个离散化的问题,我这里用了map解决。
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<algorithm>
6 #include<map>
7 #include<set>
8 #include<vector>
9 #include<queue>
10 #include<list>
11 #include<unordered_map>
12 using namespace std;
13 #define ll long long
14 const int mod=1e9+7;
15 const ll int inf=1e18+7;
16
17 const int maxn=4e5+10;
18
19 ll int num[maxn];
20
21 int main()
22 {
23 ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
24
25 int n;
26 ll int I;
27 ll int num;
28
29 while(cin>>n>>I)
30 {
31 map<ll int,int>book;
32
33 for(int i=0;i<n;i++)
34 {
35 cin>>num;
36 book[num]++;
37 }
38
39 ll int wei=I*8/n;//题意所要限制的,最大序列中不同数的个数 的取log2
40
41 if(wei>=19)//2的20次方已经大于 maxn=4e5 ,直接特判
42 {
43 cout<<0<<endl;//空间够,不用改数字
44 continue;
45 }
46
47 wei=(1<<wei);//题意所要限制的,最大序列中不同数的个数
48
49 if(book.size()<=wei)//原来数组不同数的个数已经符合条件
50 {
51 cout<<0<<endl;//不用改数字
52 continue;
53 }
54
55 vector<int>v;
56
57 for(auto it=book.begin();it!=book.end();it++)
58 { //map对key值有序,
59 v.push_back((it->second));//将value值存入数组
60 }
61
62 ll int maxx=-1;//记录最优解
63
64 ll int now=0;
65
66 for(int i=0;i<wei;i++)//再用尺取法找最优解
67 {
68 now+=v[i];
69 }
70
71 if(now>maxx)
72 maxx=now;
73
74 for(int i=wei;i<v.size();i++)
75 {
76 now+=v[i];//往后移一位
77 now-=v[i-wei];//减去前面的
78
79 if(now>maxx)//刷新最优解
80 maxx=now;
81 }
82
83 cout<<n-maxx<<endl;//n减去最大值即为最小值
84 }
85
86 return 0;
87 }