【链接】h在这里写链接


【题意】


    给你参赛者的数量以及一个整数S表示每块披萨的片数。

    每个参数者有3个参数,si,ai,bi;

    表示第i个参赛者它要吃的披萨的片数,以及吃一片第一种披萨增加的幸福感,

    以及吃一片第二种披萨增加的幸福感。



    两种披萨都能任意数量地订购。

    但是总数num有一个上限。

    就是S*num>=∑si

    且num最小。

    也就是说相当于给你一个num;

    让你求两种披萨各要买多少个a,b(a+b==num)。

    使得参赛者的幸福感尽可能高。

    (参赛者即可以选择第一种、也可以同时吃第二种)

【题解】


    如果每个人想要的披萨片数和<=S

    那么只能买一块披萨。

    则买a或买b,那么每个人都只能选A或选B

    取较大值就好。



    矛盾点在哪里?

        虽然你的a大,但是已经没有A披萨给你了

        或者,全都买B披萨更合适



    枚举最后买了多少个B披萨

    i=0

    则一开始全都吃A披萨

    i=1

    则让B-A前S大的人变成吃B披萨

    i=2

    则让B-A前2S大的人变成吃B披萨

    在i=i-1的基础上改一下就好

        记录到了哪一个人,那个人还能有多少从A->B



    i最大为num,且i*S<=∑si



    以B-A为关键字降序排一下?

【错的次数】


0

【反思】


加注释的方式真的很好。。

【代码】

#include <bits/stdc++.h>
#define ll long long
using namespace std; const int N = 1e5; struct abc{
ll a,b,rest,c;
}; int n;
ll S,temp,num,srest,ans;
abc a[N+10]; bool cmp(abc a,abc b)
{
return a.c > b.c;
} int main()
{
//freopen("F:\\rush.txt","r",stdin);
scanf("%d%lld",&n,&S);
for (int i = 1;i <= n;i++){
scanf("%lld%lld%lld",&a[i].rest,&a[i].a,&a[i].b);
a[i].c = a[i].b-a[i].a;
temp += a[i].rest*a[i].a;
srest += a[i].rest;
} //获取最多买多少个披萨
ll l = 1,r = 1e10 + 100;
while (l <= r)
{
ll mid = (l+r)>>1;
ll temp = mid*S;
if (temp >= srest)
{
num = mid;
r = mid - 1;
}else
l = mid + 1;
} sort(a+1,a+1+n,cmp);//按照B-A降序排 ans = temp;//一开始全都吃A披萨
//这个num的值可能会很大,你可能不能枚举出来全部。
//在可以的情况下,尽量贪心选。只要B披萨的数目不超过num就可以了
ll temp1 = 0,tnum = 0;//tnum是之前剩余的变成B更优的个数
//temp1是那些变成B之后答案的递增值 ll spe = num*S-srest;//多买的披萨的片数
//S片才能凑够一个B披萨 for (int i = 1;i <= n;i++)
{
//第i个人有一些变成选B披萨 if (a[i].c < 0)//这个人变成B之后答案会减小
{//用spe尽量不让他减小->本来肯定要有一些人从a变成B,现在可以用多余的填,不用让他们变了
//前提是
if (tnum + a[i].rest + spe >= S)//够凑了
{
ll dd = tnum + spe;
if (dd >= S)//不用加就能超过了
{
ans = max(ans,temp + temp1);
}else
{
ll js = S-dd;
ans = max(ans,temp + temp1 + a[i].c*js);
}
temp1 = 0;
break;
}
}
if (tnum + a[i].rest < S)//如果没有超过了1块披萨的量
{
temp1 += a[i].rest*a[i].c;
tnum += a[i].rest;
}else//超过了
{
//这一个人的a->b选了多少个?
temp += temp1;//优先加之前的 ll rr = (a[i].rest + tnum)%S;//剩余的
ll choose = a[i].rest-rr;//之后再加当前的
temp += choose*a[i].c; tnum = rr;//前些轮的剩余变成rr了
temp1 = rr*a[i].c;//temp1变成rr*a[i].c了 ans = max(ans,temp);//取最大值
//显然这个过程中B是肯定够用的
}
}
//temp1 = 1;
//printf("%lld\n",temp1);
if (tnum + spe >= S)//全为正数最后一个剩下的可能还可以和多余的凑出来一个S
{
ans = max(ans,temp + temp1);
} printf("%lld\n",ans);
return 0;
}

最新文章

  1. Shell入门教程:Shell变量
  2. 设计前沿:25个设计师向您展示 iOS 7 界面
  3. PHP程序员如何突破成长瓶颈(php开发三到四年)
  4. android 布局中 layout_gravity、gravity、orientation、layout_weight【转】
  5. Jsp的三、七、九
  6. 大整数算法[11] Karatsuba乘法
  7. gis论坛
  8. UIButton-初识IOS
  9. STL--stack/queue的使用方法
  10. Java中的statickeyword具体解释
  11. orcle :Could not initialize &quot;D:\app\Administrator\product\11.2.0\dbhome_1\bin\oci.dll&quot; Make sure you have the 32 bits Oracle Client installed.
  12. MyBatis(一):配置并使用
  13. 详解EBS接口开发之采购接收&amp;退货处理之关键API--(补充)
  14. 对半导体制造(FAB)工种的全方位解析
  15. 在Linux搭建Git服务器
  16. vue单文件组件实例1:简单单文件组件
  17. 【.NET Core项目实战-统一认证平台】第四章 网关篇-数据库存储配置(2)
  18. android checkBox选中与取消
  19. It is never too late!
  20. android xml解析中的null问题

热门文章

  1. Redis学习笔记--Redis客户端(三)
  2. HttpWebRequest使用证书请求
  3. LBP 特征
  4. enable&amp;&amp;builtin---shell内部命令
  5. 【Uva 1289】Stacking Plates
  6. Linux &quot;零拷贝&quot; sendfile函数中文说明及实际操作分析
  7. Python批量重命名指定目录下文件的两种方法
  8. 移动GPU全解读(二)
  9. oracle on linux 巡检脚本-部分
  10. 用openssl生成含有中文信息的证书