test 集合(贪心)

本文介绍了一种使用贪心策略解决特定类型数学问题的方法。通过将操作撤销,每次尽可能多地进行-1操作,并同时合并0值,实现了最优解。文章提供了一个C++实现示例,演示如何对输入数据进行排序并迭代处理以找到最小的操作次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


题解:贪心

有一个比较显然的思路就是尽可能快的将数分解,然后同时进行第一种操作。

有一个错误的思路,就是先分解成最终状态的个数,然后直到加到最大的数为止。这样为啥不对?因为你最后在+1的时候很多数都闲着了,那么不如在某些数+1的同时让某些位置分解。

于是我们考虑将操作撤销,每次讲能-1的都-1,然后同时将0两两合并,这样贪心一定是最优的。

所以我根据权值排序然后两个指针扫一遍即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 1000003
using namespace std;
int a[N],n;
int cmp(int x,int y)
{
	return x>y;
}
int main()
{
   freopen("multiset.in","r",stdin);
   freopen("multiset.out","w",stdout);
   scanf("%d",&n);
   for (int i=1;i<=n;i++) scanf("%d",&a[i]);
   sort(a+1,a+n+1,cmp);
  // for (int i=1;i<=n;i++) cout<<a[i]<<" ";
  // cout<<endl;
   int l=n; int r=n; int t=0;
   while (!a[l]) l--;
   int ans=0;
   while (true) {
   	  int size=(r-l)/2;
   	  r-=size;
   	  t++; ans++;
   	  if (r==1) break;
   	  while (a[l]==t&&l) l--;
   }	
   printf("%d\n",ans);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值