C. MP3(有难度的思维题+map使用)

在这里插入图片描述
在这里插入图片描述
这道题,我是醉了,开头我用的结构体排序,输出错在案例11;
但是这道题我对map的用法有了更新的认识;
map遍历利用迭代器遍历格式:

map<int ,int >::iterator it=mm.begin();
for(;it!=mm.end();it++){
	  int a=it->first;
	  int b=it->second;
}

还有pair的相似用法

 int a,b;
   pair<int,int> p[20];//二维 //一维只能放一个,访问格式和初始化和而为类似(其实二维也可以用结构体OK)
	for(int i=0;i<10;i++){
		cin>>a>>b;
		  p[i]=make_pair(a,b);
	}
	for(int i=0;i<10;i++){
		  cout<<p[i].first<<" "<<p[i].second<<endl;
	}
	sort(p,p+10,cmp/*这里bool cmp可以自己排序*/);

题意:给你n个数的数组,然后里面不同的数字为k个,然后我需要在I(B)范围内存下这些数字;问最小需要改变个数字多少才能存下来(区间是任意取得);
读完之后就知道我可以选一个区间按照题目修改,只要到最后成立就行;
根据题意可以列出最大的k值:
在这里插入图片描述
但是注意这里的指数可能非常大,所以可能溢出,所以这里需要讨论,如果这个k已经很大了,说明不能可能有满足条件的,所以需要改动的个数为0;
所以接下来需要解决如何存储每个数出现的个数;1.sort。2.取mm里面的元素出来;
注意取出来之后,需要对前k个相加,之后再区间平移(+,-),因为我求的是最小的改动个数,所以需要对k固定;
所以整体思路就这样了:所需要的知识map遍历+区间平移(思维);

#include<bits/stdc++.h>
#include<map>
using namespace std;
const int maxn=4e5+10;
typedef long long ll;
ll a[maxn];
 ll Cnt[maxn];//用来记录相同数的个数
map<int ,int > mm;
int main(){
   ll n,I;
   scanf("%lld %lld",&n,&I);
   for(int i=0;i<n;i++){
   	scanf("%lld",a+i);
   	mm[a[i]]++;
   }
   sort(a,a+n);
   ll g=0;//记录有多少个
map<int,int>::iterator it=mm.begin();
   for(;it!=mm.end();it++){
   	  Cnt[g++]=it->second;//这里的Cnt是记录每个数出现的次数(也就是相同数的个数),注意这里巧妙的把下标对应为不同种类了;如0,1,2表示有三种
   }
   //for(int i=0;i<g;i++)cout<<Cnt[i]<<" ";
   if(((8*I/n)>18))return puts("0"),0;//这里可以用计算机算一下取值就知道了,主要是防止溢出
    ll k=min(1ll<<(8*I/n),n);//因为最多就是n个不同,如果超出了n就取n,这里是二进制的位移运算,如果对二进制转十进制熟悉的就很好理解了
    if(k>=g) return puts("0"),0;//如果原数组本身不同的个数(g)就小于k那么就没必要改了,所以输出0
   ll ans,sum=0;
   for(int i=0;i<k;i++){
   	  sum+=Cnt[i];//计算前k个个数
   }
   ans=sum;
   for(int i=k;i<g;i++){//总长度为g区间平移
   	   sum+=Cnt[i];
   	   sum-=Cnt[i-k];
   	   ans=max(ans,sum);//每次取最大才能保证最后n-ans最小//这里是算出连续的(因为其他的可以自己选定区间变为一类)最大的不能改动的个数;
   }
   printf("%lld\n",n-ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值