zoukankan      html  css  js  c++  java
  • CF 1198 A. MP3 模拟+滑动窗口

    A. MP3

     

    题意:给你n个数,一个大小为8*I的容量,保存一个数需要多少容量取决于给定n个数的种类k,用公式 logk   计算,如果给定的容量不能保存所有数,选择减少数的种类来降低保存一个数需要的单位容量(通过替换来减少数的种类,数据的总量不变),问最少需要替换多少个数

    题解:根据输入数据的关系,可以求得保存一个数需要得最小单位容量kk=8*I n; 

    又因为kk= logk    可以解得在容量允许情况下,可以保存得最多数据种类k=2kk  

    又因为输入数据个数得限制n<=4*10^5; 即2kk  <=4*10^5;解得kk最小等于20;

    所以当kk>=20得时候,一定可以把数据完全保存----------剪枝处理

    当kk<20的时候:

    由kk= log 解得数据种类k=2^kk (快速幂)

    因为要替换的个数最少,肯定是优先替换只出现过一次的数据,

    滑动窗口处理[0,k-1]:

      用一个大小为k的窗口去判断在窗口内的要替换的最小个数

    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #include<string>
    #include<string.h>
    #include<vector>
    #include<utility>
    #include<map>
    #include<queue>
    #include<set>
    #define mx 0x3f3f3f3f
    #define ll long long
    using namespace std;
    map<ll,ll>m;
    vector<ll>p;
    ll a[400005];
    ll quick_pow(ll base,ll k)
    {
        ll ans=1;
        while(k)
        {
            if(k&1)
                ans=ans*base;
            base=base*base;
            k=k/2;
        }
        return ans;
    }
    int main()
    {
        ll n,k,cap;//容量capacity
        scanf("%lld%lld",&n,&cap);
        for(int i=0;i<n;i++)
            scanf("%lld",&a[i]);
        sort(a,a+n);
        cap=cap*8;//给定的容量有多大
        int kk=cap/n;//由输入的n和cap可以估计每存一个数需要的最少容量是多少
        if(kk>=20)//剪枝处理,如果log以2为底kk的对数等于20,解得数字的种类k=2^20,远大于给定输入数据的个数4*10^5
        {
            printf("0
    ");
            return 0;
        }
        k=quick_pow(2,kk);//由估计的容量kk去解最多可以容纳几种不同的数
        m[a[0]]++;
        p.push_back(a[0]);
        for(int i=1;i<n;i++)
        {
            if(a[i]!=a[i+1])
                p.push_back(a[i]);
            m[a[i]]++;
        }
        ll cnt=p.size();
        if(cnt<=k)//给定得容量能容纳这些数,就不用减少种类
        {
            printf("0
    ");
            return 0;
        }
        else
        {
            ll l=0,r=k-1,sum=0;
            for(int i=l;i<=r;i++)
                sum=sum+m[p[i]];//统计重复的数有几个
            ll one=n-sum;//只出现一次的数的个数
            l++;//滑动窗口,这个窗口的大小是k,[0,k-1]
            r++;
            while(r<cnt)
            {
                sum=sum-m[p[l-1]]+m[p[r]];
                ll temp=n-sum;
                one=min(one,temp);
                l++;
                r++;
            }
            printf("%lld
    ",one);
        }
    }
  • 相关阅读:
    cygwin 下配置ssh
    使用MarsEdit写博客
    bash no job control in this shell
    安装devtoolset-2:因由安装gcc 4.8而引起
    AFNetworking Property with 'retain (or strong)' attribute must be of object type
    从xib 创建 collectionViewCell
    CocoaPods 安装
    个人理解的 Https 通信流程
    cellforrowatindexpath 不执行 的原因
    do{} while(0) 的意义和用法
  • 原文地址:https://www.cnblogs.com/-citywall123/p/11347561.html
Copyright © 2011-2022 走看看