Codeforces Round #339 (Div. 2) D. Skills(模拟+枚举)

本文介绍了一个游戏中的技能升级策略问题,玩家需要通过合理的分配资源来最大化角色的力量值。力量值由满级技能数量与最低技能等级共同决定。文章提供了一种解决方案,包括技能等级的排序、满级技能数量的枚举以及最小技能等级的最大化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

time limit per test2 seconds
memory limit per test256 megabytes

Lesha plays the recently published new version of the legendary game hacknet. In this version character skill mechanism was introduced. Now, each player character has exactly n skills. Each skill is represented by a non-negative integer ai — the current skill level. All skills have the same maximum level A.

Along with the skills, global ranking of all players was added. Players are ranked according to the so-called Force. The Force of a player is the sum of the following values:

The number of skills that a character has perfected (i.e., such that ai = A), multiplied by coefficient cf.
The minimum skill level among all skills (min ai), multiplied by coefficient cm.
Now Lesha has m hacknetian currency units, which he is willing to spend. Each currency unit can increase the current level of any skill by 1 (if it’s not equal to A yet). Help him spend his money in order to achieve the maximum possible value of the Force.

Input
The first line of the input contains five space-separated integers n, A, cf, cm and m (1 ≤ n ≤ 100 000, 1 ≤ A ≤ 109, 0 ≤ cf, cm ≤ 1000, 0 ≤ m ≤ 1015).

The second line contains exactly n integers ai (0 ≤ ai ≤ A), separated by spaces, — the current levels of skills.

Output
On the first line print the maximum value of the Force that the character can achieve using no more than m currency units.

On the second line print n integers a’i (ai ≤ a’i ≤ A), skill levels which one must achieve in order to reach the specified value of the Force, while using no more than m currency units. Numbers should be separated by spaces.

Examples
input
3 5 10 1 5
1 3 1
output
12
2 5 2
input
3 5 10 1 339
1 3 1
output
35
5 5 5
Note
In the first test the optimal strategy is to increase the second skill to its maximum, and increase the two others by 1.

In the second test one should increase all skills to maximum.

这道题的意思是说,给你N个级别,满级是A,你总共还可以升M级,然后再给两个参数给你,cf和cm,然后有个式子:
满级的个数×cf+最低级的级数×cm

问,怎样分配M,使得这个式子的结果最大。

一开始我很天真的以为,尽量把大的升到满级,等到不够用了,再用剩下的来将最小的升级。然后成功地WA了。后来看了别人的博客才知道要枚举,因为有两个参数要相乘,所以并不是那么简单的贪心。而是要枚举升到满级的个数,然后再来求最小级别的级数。

然后在枚举满级的个数的时候,我们需要求的是最小级别的级数是多少。因为我们不知道怎样才能让最小的尽量大。

在这里我是一头雾水,然后,还是看了别人的博客,才一目了然。

先是将数字从大到小排序,然后从后往前求和。前面的,就是要用来枚举满级的个数的,后面的,就是用来将最小的尽量大。

我们假设有cnt个满级的,那么要将cnt个级别弄成满级的就需要
A*cnt-sum[1]+sum[cnt+1](我的for循环是从1开始的)个级别,所以一开始就要用M减去这些级别数。然后,剩下mm个级别可以让我们分配,这个时候我们很容易想到,我们把剩下的,未满级的级别数的总和求出来,算出平均数,然后把最小的,往平均数上面靠,就行了,然而并不是,因为这样算平均值,就说明要移动本来有的数字,然而那是不能移动的。

所以我们要找到一个位置h,从这个位置到最后的总和加上mm,然后算平均值,如果这个平均值大于或等于h这个位置上本来的数字,那么就将这个位置之后的所有数字都加到这个平均值上。

因为如果这个平均值大于或等于这个位置上本来的数字的话,就说明不需要移动这个数字我也能达到平均值。从左往右找,找到的第一个这样的位置就可以知道最小值的个数以及级别数了。当然,要找到这个位置,就要二分,我二分经常写挫就是了。

最后还有一点要注意的是初始化,一般我们初始化都是要初始化为0,但是我的这个代码不能简单地初始化为0,因为当M为0时,我是连循环都没有进去的,所以这个初始化,要根据一开始输入进去的数字来进行初始化,就是这一点坑了我好久,我曹。

还有里面算有多少个最小值的时候也要根据条件来初始化。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define ll long long
#define maxn 100010
const int mod=1e9+7;
using namespace std;
struct node
{
    ll val;
    int wei;
}num[maxn];
ll sum[maxn];
ll n,a,cf,cm,m;
bool cmpv(node a,node b)
{
    return a.val>b.val;
}
bool cmpw(node a,node b)
{
    return a.wei<b.wei;
}
int sear(int l,int r,ll m)
{
    if(l==r)  return l;
    if(l>r)  return r;
    int mid=(l+r)/2;

    ll f=sum[mid]+m;
    int id=n-mid+1;
    ll ff=min(f/id,a);

    if(ff>num[mid].val)  sear(l,mid,m);
    else if(ff<num[mid].val)  sear(mid+1,r,m);
    else  return mid;
}
int main()
{
    while(scanf("%I64d %I64d %I64d %I64d %I64d",&n,&a,&cf,&cm,&m)!=EOF)
    {
        memset(num,0,sizeof(num));
        memset(sum,0,sizeof(sum));
        ll ans_cnt=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%I64d",&num[i].val);
            if(num[i].val==a)  ans_cnt++;
            num[i].wei=i;
        }
        sort(num+1,num+n+1,cmpv);
        for(int i=n;i>=1;i--)
        {
            if(i==n)  sum[i]=num[i].val;
            else  sum[i]=num[i].val+sum[i+1];
        }
        ll cnt=0,mm=0,small=0,ans=0,big=0;
        ll ans_small=num[n].val;
        for(int i=0;i<=n;i++)
        {
            cnt=i;
            if(cnt==0)  mm=m;
            else  mm=m-(a*cnt-sum[1]+sum[cnt+1]);
            if(mm<=0)  break;
            if(cnt+1>n)  small=a;
            else
            {
                int h=sear(cnt+1,n,mm);
                small=min(a,(sum[h]+mm)/(n-h+1));
            }

            if(small==a)  cnt=n;

            big=small*cm+cnt*cf;

            if(big>=ans)
            {
                ans=big;
                ans_small=small;
                ans_cnt=cnt;
            }
        }

        for(int i=1;i<=n;i++)
        {
            if(i<=ans_cnt)  num[i].val=a;
            if(num[i].val<ans_small)  num[i].val=ans_small;
        }

        sort(num+1,num+n+1,cmpw);

        ans=ans_cnt*cf+ans_small*cm;

        printf("%I64d\n",ans);
        printf("%d",num[1].val);
        for(int i=2;i<=n;i++)  printf(" %d",num[i].val);
        printf("\n");

    }
    return 0;
}
内容概要:该研究通过在黑龙江省某示范村进行24小时实地测试,比较了燃煤炉具与自动/手动进料生物质炉具的污染物排放特征。结果显示,生物质炉具相比燃煤炉具显著降低了PM2.5、CO和SO2的排放(自动进料分别降低41.2%、54.3%、40.0%;手动进料降低35.3%、22.1%、20.0%),但NOx排放未降低甚至有所增加。研究还发现,经济性和便利性是影响生物质炉具推广的重要因素。该研究不仅提供了实际排放数据支持,还通过Python代码详细复现了排放特征比较、减排效果计算和结果可视化,进一步探讨了燃料性质、动态排放特征、碳平衡计算以及政策建议。 适合人群:从事环境科学研究的学者、政府环保部门工作人员、能源政策制定者、关注农村能源转型的社会人士。 使用场景及目标:①评估生物质炉具在农村地区的推广潜力;②为政策制定者提供科学依据,优化补贴政策;③帮助研究人员深入了解生物质炉具的排放特征和技术改进方向;④为企业研发更高效的生物质炉具提供参考。 其他说明:该研究通过大量数据分析和模拟,揭示了生物质炉具在实际应用中的优点和挑战,特别是NOx排放增加的问题。研究还提出了多项具体的技术改进方向和政策建议,如优化进料方式、提高热效率、建设本地颗粒厂等,为生物质炉具的广泛推广提供了可行路径。此外,研究还开发了一个智能政策建议生成系统,可以根据不同地区的特征定制化生成政策建议,为农村能源转型提供了有力支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值