Codeforces Global Round 14 C. Phoenix and Towers

一、算法分析

刚开始容易想到dfs,但是考虑集合的个数是给定的,只需要往里面填数就行了。具体的填数策略是贪心。注意题目中的一个重要条件:每个块的高度都不会超过x。

题目要求任意两个集合的规模之差不能超过x,可以转化为只要最小的集合和最大的集合规模之差不超过x即可。用小根堆维护集合,每次把方块分配到最小的集合s_min里面,则可能出现三种情况:

1)s_min仍为最小的集合,原先|s_max|-|s_min|<=x,s_min增加之后更加不会破坏这个条件。

2)原先的s_min不是最小的集合了,但也不是最大的集合,则新的s_min在原先也满足|s_max|-|s_min|<=x。

3)原先的s_min变成了最大的集合s_max:如图所示:

二、代码

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdio>
 5 #include<queue>
 6 using namespace std;
 7 const int N=100050;
 8 typedef pair<int,int> PII;                        //对于block,存大小和其属于的tower,对于Tower,存其大小和编号
 9 int n,m,x;
10 priority_queue<PII,vector<PII>,greater<PII> >q;
11 void clear(){
12     while(q.size()) q.pop();
13 }
14 int id[N];                                       
15 int main(){
16     
17     int T;
18     cin>>T;
19     while(T--){
20         scanf("%d%d%d",&n,&m,&x);
21         clear();
22         for(int i=1;i<=m;i++) q.push({0,i});
23         for(int i=1;i<=n;i++){
24             int w;
25             scanf("%d",&w);
26             PII t=q.top();
27             q.pop();
28             id[i]=t.second;
29             t.first+=w;
30             q.push(t);
31         }
32         printf("YES\n");
33         for(int i=1;i<=n;i++){
34             printf("%d ",id[i]);
35         }
36         printf("\n");
37     }
38     
39     
40     return 0;
41     
42 }

 

posted @ 2021-05-05 15:53  _rhinoceros  阅读(44)  评论(0编辑  收藏  举报