容易想到一个费用流做法:将每种蔬菜拆成p种,对应p个过期时间,每一种向可以卖的时间连边,第一次卖的奖励算在最晚过期的一种里。对于天数动态加点。不过这样边数太多了,因为第i天能卖的第i-1天一定能卖,可以改成每一种只向过期时间连边然后第i天向第i-1天连边。这样就有60分了。但费用流没有什么优化空间了。

  如果蔬菜不会过期的话,贪心做法非常显然。那么,考虑让时光倒流。这样蔬菜只会每天增加,每次贪心的选出价值最大的行了。对于奖励,拆成两种蔬菜就好。

  考虑对于单次询问具体应该怎么做。用一个大根堆维护应该选哪些蔬菜。堆里蔬菜分为两类,一类是每天都能拿的,一类只能拿一次的。每次从堆顶拿出m个蔬菜,如果是每天都能拿的再恢复回去,注意考虑各种情况。

  然后考虑多次询问。我们需要从前p天的答案倒推出前p-1天的答案。注意到第p天能选择的第p-1天一定能选择。并且前p-1天的最优选择应该包含在前p天的最优选择内,否则第p天的选择本来就更少没有理由丢掉之前的较优选择。那么从答案里去掉最小的几个使得剩下的不超过(p-1)m个就可以了。

  感觉写的姿势并不对,于是变的异常难写和丑陋不堪。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<vector>
  8. #include<queue>
  9. #include<stack>
  10. using namespace std;
  11. int read()
  12. {
  13. int x=,f=;char c=getchar();
  14. while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
  15. while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
  16. return x*f;
  17. }
  18. #define N 100010
  19. #define inf 1000000000
  20. #define ll long long
  21. int n,m,k,cnt=;
  22. ll tot=,ans[N];
  23. struct data{int v,c,x;
  24. }a[N<<];
  25. struct data2{int i,x;
  26. }Q[N];
  27. struct data3
  28. {
  29. int tim,cnt,val;
  30. bool operator <(const data3&a) const
  31. {
  32. return val<a.val;
  33. }
  34. }choose[N*];
  35. vector<data3> app[N],rec[N];
  36. priority_queue<data3> q;
  37. stack<data3> undo;
  38. bool cmp(const data2&a,const data2&b)
  39. {
  40. return a.x>b.x;
  41. }
  42. int main()
  43. {
  44. #ifndef ONLINE_JUDGE
  45. freopen("bzoj4946.in","r",stdin);
  46. freopen("bzoj4946.out","w",stdout);
  47. const char LL[]="%I64d\n";
  48. #else
  49. const char LL[]="%lld\n";
  50. #endif
  51. n=read(),m=read(),k=read();
  52. for (int i=;i<=n;i++)
  53. a[i].v=read(),a[i+n].v=a[i].v+read(),a[i].c=read()-,a[i+n].c=,a[i].x=read(),a[i+n].x=;
  54. n<<=;
  55. for (int i=;i<=k;i++) Q[i].i=i,Q[i].x=read();
  56. sort(Q+,Q+k+,cmp);
  57. for (int i=;i<=n;i++)
  58. if (a[i].x==)
  59. {
  60. if (i<=(n>>)) app[Q[].x].push_back((data3){,a[i].c,a[i].v});
  61. else app[a[i-(n>>)].x?min(Q[].x,a[i-(n>>)].c/a[i-(n>>)].x+):Q[].x].push_back((data3){,a[i].c,a[i].v});
  62. }
  63. else
  64. {
  65. if (a[i].c-1ll*a[i].x*Q[].x>) app[Q[].x].push_back((data3){,a[i].c-1ll*a[i].x*Q[].x,a[i].v});
  66. else if (a[i].c%a[i].x) app[a[i].c/a[i].x+].push_back((data3){,a[i].c%a[i].x,a[i].v});
  67. rec[min(a[i].c/a[i].x,Q[].x)].push_back((data3){min(a[i].c/a[i].x,Q[].x)+,a[i].x,a[i].v});
  68. }
  69. for (int i=Q[].x;i;i--)
  70. {
  71. for (int j=;j<app[i].size();j++) q.push(app[i][j]);
  72. for (int j=;j<rec[i].size();j++) q.push(rec[i][j]);
  73. int t=m;
  74. while (t&&!q.empty())
  75. {
  76. if (q.top().tim==)
  77. {
  78. if (t>=q.top().cnt) ans[Q[].i]+=1ll*q.top().cnt*q.top().val,t-=q.top().cnt,choose[++cnt]=q.top();
  79. else {ans[Q[].i]+=1ll*t*q.top().val;undo.push((data3){,q.top().cnt-t,q.top().val});choose[++cnt]=(data3){,t,q.top().val};t=;}
  80. }
  81. else
  82. {
  83. int tmp=q.top().cnt*(q.top().tim-i);
  84. if (t>=tmp)
  85. {
  86. ans[Q[].i]+=1ll*tmp*q.top().val;
  87. choose[++cnt]=(data3){,tmp,q.top().val};
  88. undo.push((data3){i,q.top().cnt,q.top().val});
  89. t-=tmp;
  90. }
  91. else
  92. {
  93. ans[Q[].i]+=1ll*t*q.top().val;
  94. if (t>=q.top().cnt) choose[++cnt]=(data3){,q.top().cnt*(t/q.top().cnt),q.top().val};
  95. undo.push((data3){q.top().tim-(t-)/q.top().cnt-,q.top().cnt,q.top().val});
  96. if (t%q.top().cnt) choose[++cnt]=(data3){,t%q.top().cnt,q.top().val},undo.push((data3){,q.top().cnt-t%q.top().cnt,q.top().val});
  97. t=;
  98. }
  99. }
  100. q.pop();
  101. }
  102. while (!undo.empty()) q.push(undo.top()),undo.pop();
  103. }
  104. sort(choose+,choose+cnt+);
  105. int tot=;for (int i=;i<=cnt;i++) tot+=choose[i].cnt;
  106. int t=;long long sum=ans[Q[].i];cnt=;
  107. for (int i=Q[].x-;i;i--)
  108. {
  109. while (tot>i*m)
  110. {
  111. if (tot-i*m>=choose[cnt].cnt) sum-=1ll*choose[cnt].cnt*choose[cnt].val,tot-=choose[cnt++].cnt;
  112. else sum-=1ll*choose[cnt].val*(tot-i*m),choose[cnt].cnt-=tot-i*m,tot=i*m;
  113. }
  114. if (i==Q[t].x) ans[Q[t++].i]=sum;
  115. }
  116. for (int i=;i<=k;i++) printf(LL,ans[i]);
  117. return ;
  118. }

BZOJ4946 NOI2017蔬菜(贪心+堆)的更多相关文章

  1. bzoj4946: [Noi2017]蔬菜 神烦贪心

    题目链接 bzoj4946: [Noi2017]蔬菜 题解 挺神的贪心 把第次买的蔬菜拆出来,记下每种蔬菜到期的日期,填第一单位蔬菜比其他的要晚 按价格排序后,贪心的往前面可以填的位置填就可以了.找可 ...

  2. BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流

    题目链接: [Noi2017]蔬菜 题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量), ...

  3. [NOI2017]蔬菜 贪心

    题面: [NOI2017]蔬菜 题解: 首先每天蔬菜会变质这点并不好处理,我们考虑让时间倒流,从后向前处理,这样的话就相当于每天都会得到一定量的蔬菜. 这样做有什么好处呢? 我们可以发现一个性质:如果 ...

  4. bzoj4946 Noi2017 蔬菜

    题目描述 小 N 是蔬菜仓库的管理员,负责设计蔬菜的销售方案. 在蔬菜仓库中,共存放有nn 种蔬菜,小NN 需要根据不同蔬菜的特性,综合考虑各方面因素,设计合理的销售方案,以获得最多的收益. 在计算销 ...

  5. NOI2017蔬菜(贪心)

    小 N 是蔬菜仓库的管理员,负责设计蔬菜的销售方案. 在蔬菜仓库中,共存放有 n 种蔬菜,小 N 需要根据不同蔬菜的特性,综合考虑各 方面因素,设计合理的销售方案,以获得最多的收益. 在计算销售蔬菜的 ...

  6. BZOJ.4946.[NOI2017]蔬菜(贪心 离线)

    题目链接 因为有删除,考虑倒序处理某个p的询问. 那么每天删除xi的蔬菜就变成了每天运来xi的蔬菜.那么我们取当前最优的即可,早取晚取都一样,不需要留给后面取,还能给后面更优的留出空间. 这样就只需考 ...

  7. 【BZOJ4946】[NOI2017]蔬菜(贪心)

    [BZOJ4946][NOI2017]蔬菜(贪心) 题面 BZOJ 洛谷 UOJ 题解 忽然发现今年\(NOI\)之前的时候切往年\(NOI\)的题目,就\(2017\)年的根本不知道怎么下手(一定是 ...

  8. [NOI2017]蔬菜(贪心+递推)

    这题很有思维难度,乍一看基本无从下手. 给每个蔬菜钦定退役的时间显然很困难,可以考虑让时光倒流,从后向前递推,然后就变成了某个时间点有一部分蔬菜服役,而已经服役的蔬菜不会退役了.然后就可以直接考虑贪心 ...

  9. [NOI2017]蔬菜

    [NOI2017]蔬菜 题目描述 大意就是有\(n\)种物品,第\(i\)个物品有\(c_i\)个,单价是\(a_i\).然后每天你可以卖出最多\(m\)个物品.每天结束后第\(i\)种物品会减少\( ...

随机推荐

  1. elasticsearch6.1 安装问题

    问题:Caused by: java.lang.RuntimeException: can not run elasticsearch as root [root@localhost logs]# a ...

  2. java中使用阻塞队列实现生产这与消费这之间的关系

    需求如下: 有一个生产者和一个消费者,生产者不断的生产产品,消费这不断的消费产品.产品总数为N. 1.生产顺序按队列的方式,先进先出. 2.生产者和消费这可以同时进行. 3.当生产者生产了N个产品后不 ...

  3. LOJ2538 PKUWC2018 Slay the Spire DP

    传送门 不想放题面了,咕咕咕咕咕 这个期望明明是用来吓人的,其实要算的就是所有方案的最多伤害的和. 首先可以知道的是,能出强化牌就出强化牌(当然最后要留一张攻击牌出出去),且数字尽量大 所以说在强化牌 ...

  4. PowerDesign 16.0 生成的SQL Server2000 数据库脚本时MS_Description不存在的问题解决

    根据网上查询到的资料,找到了解决方法,原文出自:http://www.cnblogs.com/24tt/p/5047257.html PowerDesign 16.0 生成的Script语句,Sql2 ...

  5. npm install xxx --save-dev 与npm install xxx --save 的区别

    正常情况下: 当你为你的模块安装一个依赖模块时 1.你得先安装他们(在模块根目录下npm install module-name) 2.连同版本号手动将他们添加到模块配置文件package.json中 ...

  6. cython学习

    学习网址:http://blog.csdn.net/i2cbus/article/details/23791309

  7. nginx解决前端跨域配置

    在nginx.conf文件中 添加如上配置: 在ajax中将原来的 url:http://192.168.1.127:8905/findItem 改成:'http://localhost/findIt ...

  8. 如何使用chrome浏览器进行js调试找出元素绑定的点击事件

    大家有没有遇到这样的一个问题,我们在分析一些大型电子商务平台的Web前端脚本时,想找到一个元素绑定的点击事件,并不是那么容易,因为有些前端脚本封装的比较隐蔽,甚至有些加密脚本,用传统的查找元素ID.或 ...

  9. TiDB入门(四):从入门到“跑路”

    前言 前面三章基本把 TiDB 的环境弄好了,也做了一下简单测试,有兴趣的同学可以看一下: TiDB 入门(一):TiDB 简介 TiDB 入门(二):虚拟机搭建 TiDB-Ansible 部署方案 ...

  10. 大话重构连载15:采用Mock技术完成测试

    第五次重构我们引入了数据库的设计,用户信息要从数据库中读取,问候语库存储在数据库中,并支持添加与更新.数据库的引入使自动化测试变得困难了,因为数据状态总是变化着的,而这种变化使得测试过程不能复现,这是 ...