题目来源: CodeForces
基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题
现在有n个货物,第i个货物的重量是 2wi 。每次搬的时候要求货物重量的总和是一个2的幂。问最少要搬几次能把所有的货物搬完。
样例解释:
1,1,2作为一组。
3,3作为一组。
Input
单组测试数据。
第一行有一个整数n (1≤n≤10^6),表示有几个货物。
第二行有n个整数 w1,w2,...,wn,(0≤wi≤10^6)。
Output
输出最少的运货次数。
Input示例
样例输入1
5
1 1 2 3 3
Output示例
样例输出1
2
打练习赛的时候,自己想的思路,T 了n发,最后学长看了给我说加个快读就行了,emmmm;
还有一种思路,用有优先队列写,但是没有我的思路优化过后快;优先队列可以看这篇博客
优先队列版:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<math.h>
#include<map>
#include<vector>
#include<stack>
#include<iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1000105;
priority_queue<int,vector<int>,greater<int> >q;
//优先队列,注意要改成升序
int main()
{
int i,a,n,ans=0,t1,t2;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&a);
q.push(a);
}
while(!q.empty())
{
if(q.size()==1)
{
ans++;
break;
}
t1=q.top();
q.pop();
t2=q.top();
if(t1==t2)//相同的就两个都出队列,然后添加进一个t1+1
{
q.pop();
q.push(t1+1);
}
else//不同就直接答案+1
ans++;
}
printf("%d\n",ans);
return 0;
}
自己的思路:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<math.h>
#include<map>
#include<vector>
#include<stack>
#include<iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1000105;
int mark[N];
inline int read()//快读优化
{
int f=1,num=0;
char ch=getchar();
while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(0!=isdigit(ch)) num=(num<<1)+(num<<3)+ch-'0',ch=getchar();
return num*f;
}
int main()
{
int n,mini=inf,maxx=0,a,i,ans=0;
scanf("%d",&n);
for(i=0;i<n;i++)
{
a=read();
mark[a]++;
if(a>maxx) maxx=a;
if(a<mini) mini=a;
}
maxx+=30;//注意要加30左右
for(i=mini;i<=maxx;i++)
{
mark[i+1]+=mark[i]/2;//如果当前次幂出现两次以上,就可以向更高次幂转换
ans+=mark[i]&1;//位运算,相当于模
}
printf("%d\n",ans);
return 0;
}