BZOJ.4946.[NOI2017]蔬菜(贪心 离线)
因为有删除,考虑倒序处理某个p的询问。
那么每天删除xi的蔬菜就变成了每天运来xi的蔬菜。那么我们取当前最优的即可,早取晚取都一样,不需要留给后面取,还能给后面更优的留出空间。
这样就只需考虑现在了。于是我们能得到p为某个值的答案。多次询问显然需要递推。
而p-1与p相比只是少卖了m的蔬菜。把收益最小的m个删掉即可。
注意堆的插入删除顺序。
复杂度\(O(mqlogn)\)。
还有一种求询问p的方法,是直接按蔬菜价值排序,然后每次找到其出现位置往前覆盖。如果某天已卖m则用并查集合并掉。
递推的时候sort一遍挨着删就可以。
感觉离散化后线段树可做,第一次购买收益单独算一个,每个节点维护区间当前蔬菜种数、蔬菜总量、每天减少量。
正序做,每一天就选m个最大的,然后减掉这m个。
在某种蔬菜消失的那天直接Delete掉这种蔬菜(如果剩下1个下一天则Delete掉拆开的第一次购买收益)。
这样复杂度还与m无关。
不过...算了我就想想...写了写就弃了。
//9424kb 1132ms
#include <queue>
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 400000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define mp std::make_pair
#define pr std::pair<LL,int>
#define MAX 100000
typedef long long LL;
const int N=1e5+3;
int A[N],S[N],tot[N],dec[N],use[N];
LL Ans[N];
std::vector<int> v[N];
std::queue<int> tmp;
std::priority_queue<pr> q1;
std::priority_queue<pr,std::vector<pr>,std::greater<pr> > q2;
char IN[MAXIN],*SS=IN,*TT=IN;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
int main()
{
int n=read(),m=read(),Q=read();
for(int i=1; i<=n; ++i)
{
A[i]=read(),S[i]=read(),tot[i]=read(),dec[i]=read();
if(!dec[i]) v[MAX].push_back(i);//上界!
else v[std::min(MAX,(tot[i]+dec[i]-1)/dec[i])].push_back(i);
}
LL ans=0;
for(int i=MAX; i; --i)
{
for(int j=0,k,l=v[i].size(); j<l; ++j)//处理第一次购买
k=v[i][j], q1.push(mp(A[k]+S[k],k));
for(int l=m; l&&!q1.empty(); q1.pop())
{
int x=q1.top().second;
if(!use[x])
use[x]=1, ans+=q1.top().first, q1.push(mp(A[x],x)), --l;
else
{
int cnt=std::min(l,tot[x]-use[x]-(i-1)*dec[x]);
ans+=1ll*q1.top().first*cnt, l-=cnt;
if((use[x]+=cnt)!=tot[x]/*x=0可能会用完!*/) tmp.push(x);//delete
}
}
while(!tmp.empty()) q1.push(mp(A[tmp.front()],tmp.front())), tmp.pop();
}
Ans[MAX]=ans; int sum=0;
for(int i=1; i<=n; sum+=use[i++])
if(use[i]==1) q2.push(mp(A[i]+S[i],i));
else if(use[i]) q2.push(mp(A[i],i));
for(int i=MAX-1; i; --i)
{
Ans[i]=ans=Ans[i+1];
if(sum<=m*i) continue;//总数不够!
for(int l=sum-i*m/*同上!*/; l&&!q2.empty(); )
{
int x=q2.top().second;
if(use[x]==1) ans-=q2.top().first, --l, q2.pop();
else
{
int cnt=std::min(l,use[x]-1);
ans-=1ll*q2.top().first*cnt, l-=cnt;
if((use[x]-=cnt)==1) q2.pop(), q2.push(mp(A[x]+S[x],x));
}
}
sum=i*m, Ans[i]=ans;
}
while(Q--) printf("%lld\n",Ans[read()]);
return 0;
}
BZOJ.4946.[NOI2017]蔬菜(贪心 离线)的更多相关文章
- 【刷题】BZOJ 4946 [Noi2017]蔬菜
Description http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf Solution 网上大部分都是并查集写法,但是有大神写了非并查集写 ...
- 4946: [Noi2017]蔬菜
4946: [Noi2017]蔬菜 http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf 分析: 贪心. 首先可以将一个蔬菜拆成两个,一个是有加成 ...
- [NOI2017]蔬菜 贪心
题面: [NOI2017]蔬菜 题解: 首先每天蔬菜会变质这点并不好处理,我们考虑让时间倒流,从后向前处理,这样的话就相当于每天都会得到一定量的蔬菜. 这样做有什么好处呢? 我们可以发现一个性质:如果 ...
- NOI2017蔬菜(贪心)
小 N 是蔬菜仓库的管理员,负责设计蔬菜的销售方案. 在蔬菜仓库中,共存放有 n 种蔬菜,小 N 需要根据不同蔬菜的特性,综合考虑各 方面因素,设计合理的销售方案,以获得最多的收益. 在计算销售蔬菜的 ...
- 【BZOJ4946】[NOI2017]蔬菜(贪心)
[BZOJ4946][NOI2017]蔬菜(贪心) 题面 BZOJ 洛谷 UOJ 题解 忽然发现今年\(NOI\)之前的时候切往年\(NOI\)的题目,就\(2017\)年的根本不知道怎么下手(一定是 ...
- bzoj4946: [Noi2017]蔬菜 神烦贪心
题目链接 bzoj4946: [Noi2017]蔬菜 题解 挺神的贪心 把第次买的蔬菜拆出来,记下每种蔬菜到期的日期,填第一单位蔬菜比其他的要晚 按价格排序后,贪心的往前面可以填的位置填就可以了.找可 ...
- [NOI2017]蔬菜
[NOI2017]蔬菜 题目描述 大意就是有\(n\)种物品,第\(i\)个物品有\(c_i\)个,单价是\(a_i\).然后每天你可以卖出最多\(m\)个物品.每天结束后第\(i\)种物品会减少\( ...
- BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流
题目链接: [Noi2017]蔬菜 题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量), ...
- [NOI2017]蔬菜——时光倒流+贪心
题目链接 题解: 貌似一眼看过去是一个贪心. 其他的算法要记录的东西就太多了. 部分分其实很高.但是没有什么提示. 想一些套路:二分?不行还要贪心判断. 分治?前后取法是有影响的. 时光倒流? 也许可 ...
随机推荐
- bzoj千题计划200:bzoj3106: [cqoi2013]棋盘游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=3106 白棋如果第一步不能赢,那么一定输 因为可以黑棋走的距离比白棋大,黑棋可以下一步吃掉白棋,也可以 ...
- 基础知识点 关于 prototype __proto__
基础知识点 关于 prototype __proto__ 供js新手参考 JavaScript 的一些基础知识点: 在 JavaScript 中,所有对象 o 都拥有一个隐藏的原型对象(在 Fire ...
- Linux - seq 预设外部命令
seq 是Linux 中一个预设的外部命令,一般用作一堆数字的简化写法. 常用参数: # 不指定起始数值,则默认为 1 -s # 选项主要改变输出的分格符, 预设是 \n -w # 等位补全,就是宽度 ...
- shiro登录成功之后跳转原路径
通过 WebUtils.getSavedRequest(request) 来获取shiro保存在session登录之前的url 1:java Controller代码 @PostMapping(&qu ...
- ViewGroup.layout(int l, int t, int r, int b)四个输入参数的含义
ViewGroup.layout(int l, int t, int r, int b)这个方法是确定View的大小和位置的,然后将其绘制出来,里面的四个参数分别是View的四个点的坐标,他的坐标不是 ...
- 在 Linux 上找出并解决程序错误的主要方法【转】
转自:https://www.ibm.com/developerworks/cn/linux/sdk/l-debug/index.html 本文讨论了四种调试 Linux 程序的情况.在第 1 种情况 ...
- mysqldump只导出表结构或只导出数据的实现方法【转】
mysql mysqldump 只导出表结构 不导出数据 mysqldump --opt -d 数据库名 -u root -p > xxx.sql 备份数据库 #mysqldump 数据库名 & ...
- 计算机底层知识拾遗(九)深入理解内存映射mmap
内存映射mmap是Linux内核的一个重要机制,它和虚拟内存管理以及文件IO都有直接的关系,这篇细说一下mmap的一些要点. 修改(2015-11-12):Linux的虚拟内存管理是基于mmap来实现 ...
- (转载)mysql:“Access denied for user 'root'@'localhost'”
原文地址:http://www.linuxidc.com/Linux/2007-05/4338.htm # /etc/init.d/mysql stop# mysqld_safe --user=mys ...
- 六、vue路由Vue Router
一.基本概念 route, routes, router 1, route,它是一条路由,由这个英文单词也可以看出来,它是单数, Home按钮 => home内容, 这是一条route, a ...