zoukankan      html  css  js  c++  java
  • codeforces1198A MP3 思维+双指针(滑动窗口)

    网址:http://codeforces.com/problemset/problem/1198/A

    题意:

    给出$n$个数和一个有$I$个byte(就是$8*I$个bit)的硬盘,取一个下界$L$和一个上界$R$,$L leq R$,数据中小于$L$的全部改成$L$,大于$R$的全部改成$R$,使得剩下的数的种类数$K leq 2^{ frac{8*I}{n}}$,求需要改变的数的最小值,$n leq 4e5$。

    题解:

    数的种类最大就是$n$的上界,所以$2^{frac{8*I}{n}}$大于$4e5$直接输出$0$,否则离散化所有数字,统计数字的个数$K$,如果$K leq 2^{ frac{8*I}{n}}$直接输出$0$,否则使用一个长度是$k_0=2^{ frac{8*I}{n}}$的滑动窗口枚举最小值即可。

    易错点$!!!$:

    $1、$快速幂的倍率和中间结果容易溢出或者漏解,需要特别注意,理解快速幂的过程。

    $2、$不能够从两端逼近直到区间长为$k_0$,双指针可能会在一个次优解中停止。

    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    int num[400005],tmp[400005],sum[400005];
    #define int128 __int128
    const long long INF=0x3f3f3f3f3f3f3f3f;
    
    long long poww(long long a,long long b)
    {
        long long res=1;
        while(b)
        {
            if(a>=4e5+1)
                return INF;
            if(b&1)
                res=res*a;
            a=a*a;
            b>>=1;
            if(res>=4e5+1)
                return INF;
        }
        return res;
    }
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        int n,I;
        cin>>n>>I;
        for(int i=0;i<n;++i)
            cin>>num[i];
        int maxk=(8*I)/n;
        long long Kmax=poww(2,maxk);
        //离散化计数
        for(int i=0;i<n;++i)
            tmp[i]=num[i];
        sort(tmp,tmp+n);
        int nnew=unique(tmp,tmp+n)-tmp;
        if(nnew<=Kmax)
            cout<<0<<endl;
        else
        {
            int ans,minn=0;
            memset(sum,0,sizeof(sum));
            for(int i=0;i<n;++i)
                ++sum[lower_bound(tmp,tmp+nnew,num[i])-tmp];
            //sort(sum,sum+nnew);
            //for(int i=0;i<nnew;++i)
                //cout<<sum[i]<<endl;
            for(int i=0;i<Kmax;++i)
                minn+=sum[i];
            ans=n-minn;
            for(int i=Kmax;i<nnew;++i)
            {
                minn=minn-sum[i-Kmax]+sum[i];
                ans=min(ans,n-minn);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    

     

  • 相关阅读:
    你最该知道的事(职场)
    C++ OTL MySQL(Windows/Linux) V8.1
    mysql字符串替换
    NYOJ 17 单调递增最长子序列
    IOS Sqlite用户界面增删改查案例
    时间戳工具类
    2014年7月10日,我人生的最重要Upgrade
    Java线程演示样例
    hiho模拟面试题2 补提交卡 (贪心,枚举)
    Android.mk添加本地程序和库的经常使用模版
  • 原文地址:https://www.cnblogs.com/Aya-Uchida/p/11286184.html
Copyright © 2011-2022 走看看