盒子 贪心

题目:

盒子
(box.cpp/in/out 1s 256M)
小D在玩堆盒子的游戏,每个盒子有一个强度,代表它上方最多能堆多少个
盒子。由于盒子都是一样大的,所以不能在一个盒子上并列放超过一个盒子。
现在小D有n个盒子,第i个盒子的强度为xi。小D想知道,如果他要把这些盒
子全部堆起来,至少要堆多少堆。
Input
第一行读入一个整数n,代表小D有的盒子个数。
第二行读入n个整数,第i个整数xi表示第i个盒子的强度。
Output
一个整数表示小D至少要堆多少堆。
n≤500000,xi≤1000000000。
Sample Input
5
0 2 1 1 2
Sample Output
2

法一:

此题用小根堆来维护。

将所有盒子从小到大排序。然后一个个加,这时不再关心盒子本身的那个所谓堆数的限制
拿样例来说,0 1 1 2 2
将0这个盒子放到堆中,记值为1代表有一个大小为一个盒子的盒子堆再看数字1,值大于等于目前,所以可以加到这个盒子堆中,盒子堆的体积变2对于第三个数字1,其已不能放到第一堆的盒子堆中了,于是另开一堆出来。其中Heap中有两个元素,一个为1,一个为2,对于第四个数字2,显然可以放到第二堆的盒子堆中。。。

初始push值为1,因为无论怎样第一个(必须从小到大排序) 一定可以为1堆,若枚举的值大于等于目前堆顶元素,就加入此堆,否则就另开一个堆另一个堆顶元素肯定也为1因为此时另一个堆也有一个元素。

code:

 1 #include<bits/stdc++.h>
 2 #pragma GCC optimize(3)
 3 const int N=5e5+10;
 4 using namespace std;
 5 int n,a[N];
 6 int ans=1;
 7 priority_queue< int,vector<int>,greater<int> >q; 
 8 inline int read(){
 9     int x=0,f=1;char ch=getchar();
10     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
11     while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
12     return x*f;
13 }
14 inline void write(int x){
15      char F[200];
16      int tmp=x>0?x:-x ;
17      if(x<0)putchar('-') ;
18      int cnt=0 ;
19         while(tmp>0)
20         {
21             F[cnt++]=tmp%10+'0';
22             tmp/=10;
23         }
24         while(cnt>0)putchar(F[--cnt]) ;
25 }
26 int main()
27 {
28     n=read();
29     for(int i=1;i<=n;i++){
30         a[i]=read();
31     }
32     sort(a+1,a+n+1);
33     q.push(1);
34     for(int i=2;i<=n;i++){
35         int x=q.top();
36         if(x<=a[i]){
37             q.pop();
38             x++;
39             q.push(x);
40         }
41         else{
42             ans++;
43             q.push(1);
44         }
45     }
46     printf("%d\n",ans);
47     return 0;
48 }

 法二:

直接两个for循环查找,方法同样类似

找大于等于当前值

若小于当前值就再开一堆,即ans++

code:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,ans,sum,maxn;
 4 int a[500001];
 5 bool flag[500001];
 6 int main()
 7 {
 8     cin>>n;
 9     for(int i=1;i<=n;i++)
10         cin>>a[i];
11     sort(a+1,a+n+1);
12     maxn=a[n];
13     for(int i=1;i<=n;i++)
14         if(!flag[i])
15         {
16             ans++;
17             sum=0;  
18             for(int k=i;k<=n;k++)
19                 if(!flag[k]&&a[k]>=sum)
20                 {
21                     sum++;
22                     flag[k]=true;
23                     if(sum>maxn)break;
24                 }   
25         }
26     cout<<ans;
27     return 0;
28 }  

猜你喜欢

转载自www.cnblogs.com/nlyzl/p/11674374.html