CF 1198 A. MP3 + analog sliding window

A. MP3

 

 

 

Meaning of the questions: n give you the number, a size 8 * I capacity, save a number of how much capacity is required depends on the type of a given number of n k, using the formula  log k  calculations, if a given capacity can not save all number, choose to reduce the number of types to reduce the storage capacity required for a number of units (to reduce the number of types by replacing the total amount of data change), Q needs to be replaced much minimum number 

 

Solution: The relationship between the input data stored can be determined to obtain a minimum required number of unit volume = KK . 8 the I * n-; 

= And because KK  log K     can solve for the case in capacity allows, data types can be stored most 2 = K KK  

And because the input data may limit the number n <= 4 * 10 ^ 5 ; i.e. 2 kk   <=. 5. 4 * 10 ^; kk solve for the minimum equal to 20;

So when kk> = 20 too, they must be fully saved data pruning process ----------

 

When kk <20 when:

A = KK  log   solve for the data type k = 2 ^ kk (Fast Power)

Because the minimum number to be replaced, the replacement must be a priority of the data appeared only once,

Sliding window processing [0, k-1]:

  With a window of size k is determined in the window to the minimum number to be replaced

 

 

#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\n");
        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\n");
        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\n",one);
    }
}

 

 

 

Guess you like

Origin www.cnblogs.com/-citywall123/p/11347561.html