题目链接
https://codeforces.com/contest/1515/problem/C
算法思路
将id数组排序,按照方块的高度排序{return a[c]>a[d]},优先放最大的
优先队列,当前塔中,高度最低的塔,放上去
然后遍历完所有的之后,再判断其中最高的塔和最低的塔的高度查是否大于h即可
证明:贪心策略,矛盾法
答案不存在NO,就离谱
如果存在的话,因为初始条件均小于h,所以差值也就小于h,如果最后出现了大于等于h的情况,就说明差值是两个方块,这也就和贪心法矛盾,所以答案必然是YES
代码实现
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
#define el '\n'
#define cl putchar('\n')
#define pb push_back
#define fir first
#define sec second
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vci;
typedef map<int,int> mii;
typedef mii::iterator mii_it;
typedef mii::reverse_iterator mii_rit;
const int N=1e5+10,M=1e3+10;
int T,n,m,x,y,k,h;
;int v[N];
int mx,mi;
bool cmp(int c,int d){
return v[c]>v[d];
}
void get(vci p){
for(int i=1;i<p.size();i++){
if(mx<p[i]){
mx=p[i];
}
if(mi>p[i]){
mi=p[i];
}
}
}
int main() {
cin.tie(0);
cout.tie(0);
cin>>T;
while(T--) {
priority_queue<pii> q;
cin>>n>>m>>h;
vci t(n,0);
for(int i=0;i<n;i++){
cin>>v[i];
}
for(int i=1;i<=m;i++)q.push({0,i});
for(int i=0;i<t.size();i++){
t[i]=i;
// cout<<t[i]<<" ";
}
sort(t.begin(),t.end(),cmp);
vci w(n);
vci pre(m+1);
for(int i=0;i<n;i++){
pii now=q.top();
q.pop();
now.first-=v[t[i]];
w[t[i]]=now.sec;
q.push(now);
}
for(int i=0;i<n;i++){
pre[w[i]]+=v[i];//建立高塔
}
mx=INT_MIN,mi=INT_MAX;
get(pre);
if(mx-mi<=h){
cout<<"YES"<<el;
for(int i=0;i<n;i++){
cout<<w[i]<<" ";
}
cout<<el;
}
else cout<<"NO"<<el;
}
}