D. 摊位分配

  • 你的做法模拟到了所有社团都至少分到了1个格子,用double实现会有精度问题,既然可以避免就避免吧
  • 题解则观察到了分界值和划分出的席位数之间良好的单调关系,采用二分的方法求解
  • 但这种做法有严重的精度问题,根源在于分界值趋近于0,可以通过取log或者拆分整数和小数的方法优化
#include <bits/stdc++.h>
using namespace std;
long long w[100005],cnt[100005];
long long ans[100005],u[100005];
struct t1
{
	long long cnt,w;
	long long i;
	bool pd;
};
auto cmpt=[](t1 a,t1 b)
{
	if(a.w*(1<<b.cnt)!=b.w*(1<<a.cnt))
	{
		return a.w*(1<<b.cnt)<b.w*(1<<a.cnt);
	}
	if(a.pd^b.pd)
	{
		return b.pd==true;
	}
	if(a.w!=b.w)
	{
		return a.w<b.w;
	}
	return a.i>b.i;
};
priority_queue<t1,vector<t1>,decltype(cmpt)>q(cmpt);
bool cmp(long long a,long long b)
{
	if(w[a]*(1<<cnt[b])!=w[b]*(1<<cnt[a]))
	{
		return w[a]*(1<<cnt[b])>w[b]*(1<<cnt[a]);
	}
	if(w[a]!=w[b])
	{
		return w[a]>w[b];
	}
	return a<b;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	long long n,h;
	cin>>n>>h;
	for(long long i=1;i<=n;i++)
	{
		cin>>w[i];
		q.push((t1){0,w[i],i,true});
		u[i]=i;
	}
	long long sum=0;
	while(sum!=n&&h!=0)
	{
		t1 n1=q.top();
		q.pop();
		long long i=n1.i;
		ans[i]++;
		cnt[i]++;
		h--;
		sum+=(ans[i]==1);
		q.push((t1){cnt[i],w[i],i,false});
	}
	if(h>0)
	{
		for(long long i=1;i<=n;i++)
		{
			ans[i]+=(h/n);
		}
		h%=n;
		sort(u+1,u+n+1,cmp);
		for(long long i=1;i<=h;i++)
		{
			ans[u[i]]++;
		}
	}
	for(long long i=1;i<=n;i++)
	{
		cout<<ans[i]<<" ";
	}
	cout<<endl;
	return 0;
}
posted @ 2025-01-19 23:07  D06  阅读(9)  评论(0)    收藏  举报
//雪花飘落效果