码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 1199C mp3(尺取)

时间:2020-07-03 23:09:02      阅读:63      评论:0      收藏:0      [点我收藏+]

标签:范围   +=   需要   line   ++   min   连续   while   inline   

题目链接

题目大意

??(懒得写了直接搬的学长的翻译)已知共有n个音符, 一共有K个音符强度。每种音符强度需要A=logK(向上取整)位用来存储。整体所需空间是\(N\times A\)位。例如十个音符、一共四种音符强度,则需要10*log4=20位存储。 但由于武学长的硬盘存储空间不足,我们需要选取一定范围的音符强度保持不变,小于该范围的修改为该范围的最小值,大于该范围修改为该范围的最大值。 但武学长是对音质极为注重,他希望你能提供一个程序,将音频压缩位最大I字节的文件并最小程度的修改音符数量。 提示:一个字节等于8位。

解题思路

??显然,如果初始状态需要的空间小于\(8 \times I\)的话,就需要缩小音符的种类,既然所得的是一个连续的区间,那么就只要两种缩法,要么从头开始缩,要么从尾部开始缩。我们枚举左边界L,可以发现R是不断增大的,所以就可以通过尺取来解决问题,不过因为音符的强度范围问题,需要在尺取之前做一下离散化以方便尺取。

代码

const int maxn = 4e5+10;
int a[maxn], b[maxn], cnt[maxn], n, I;
ll solve(int x) {
    if (x==1) return 0;
    return ceil(log2l(x));
}
int main() {
    scanf("%d%d",&n,&I);
    for (int i = 0; i<n; ++i) {
        scanf("%d",&a[i]);
        b[i] = a[i];
    }
    sort(b,b+n);
    int k = unique(b,b+n)-b;
    for (int i = 0; i<n; ++i) {
        a[i] = lower_bound(b,b+k,a[i])-b;
        ++cnt[a[i]];
    }
    int r = 0, ans = INF, sum = 0;
    for (int i = 0; i<k; ++i) {
        while(r<=k && solve(r-i+1)*n<=8LL*I) {
            sum += cnt[r++];
            ans = min(n-sum,ans);
        }
        sum -= cnt[i];
    }
    printf("%d\n",ans);
    return 0;
}

Codeforces 1199C mp3(尺取)

标签:范围   +=   需要   line   ++   min   连续   while   inline   

原文地址:https://www.cnblogs.com/shuitiangong/p/13233016.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!