4946: [Noi2017]蔬菜
4946: [Noi2017]蔬菜
http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf
分析:
贪心。
首先可以将一个蔬菜拆成两个,一个是有加成的,一个是没有加成的。
贪心:1、多卖出些贵的好,所以先考虑贵的蔬菜;2、对于一个蔬菜,卖的越晚越好(越晚,可以给前面留出位置。)
然后对蔬菜按价格排序,从后往前考虑卖的时间,尽量卖。如果一天的m个蔬菜全卖了,那么下次走到这个位置就没用了,所以直接并查集合并即可。所以复杂度是$O(mn \times 并查集的复杂度)$。现在可以贪心的处理出任意天的最大买的获益。
如果对于每次询问都这样做,显然会超时。考虑优化。如果知道某一天,是否可以快速的知道相邻的一天。
正着考虑,每次加入一些位置,因为上面的贪心是从最后一天贪心的,现在最后一天变了,所以无法推出下一天,没有什么关系。
正难则反,反过来考虑,每次相当于减去一些蔬菜,所以可以减去最便宜的。
做法:用上面的贪心处理处n天的最大获益,并记录每天卖了多少,用栈记录所有卖的蔬菜(上面的一定是价值小的),然后计算这一天需要减去多少颗蔬菜,从栈顶开始减。复杂度$O(n+D)$。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ; struct Node{
int w, siz, sub, d; // 价值,数量,每天减少的,消失的一天
Node() {}
Node(int _w,int _siz,int _sub,int _d) { w = _w, siz = _siz, sub = _sub, d = _d; }
bool operator < (const Node &A) const {
return w > A.w;
}
}A[N];
int n, m, k, Top;
int sk[N], skw[N], d[N], fa[N], q[N];
LL ans[N], sumr[N], del[N], Sum; int find(int x) {
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void Merge(int a,int b) {
a = find(a), b = find(b);
if (a != b) fa[a] = b;
}
void Calc(int i,int s,int w) { // 第i天,卖价值为w的菜,卖了s个
Sum += 1ll * s * w;
d[i] += s;
sk[Top] += s, skw[Top] = w; // skw[Top]+=w!!!
if (d[i] == m) Merge(i, i - );
}
int main() {
n = read(), m = read(), k = read();
int tot = , D = ;
for (int i=; i<=n; ++i) {
int w = read(), fir = read(), siz = read(), sub = read();
A[++tot] = Node(w + fir, , , sub ? (siz - ) / sub + : N - );
if (--siz) A[++tot] = Node(w, siz, sub, sub ? (siz - ) /sub + : N - );
}
for (int i=; i<=k; ++i)
q[i] = read(), D = max(q[i], D); sort(A + , A + tot + );
for (int i=; i<=D; ++i) fa[i] = i;
for (int i=; i<=tot; ++i) {
++Top;
int idx = find(min(A[i].d, D));
int sum = (idx - ) * A[i].sub, r = A[i].siz - sum; // sum前面卖的,r现在卖的
while (idx && r) {
int mn = min(m - d[idx], r); // d[idx] not d[idx - 1]
Calc(idx, mn, A[i].w);
r -= mn;
int p = idx;
idx = find(idx - );
p -= idx;
if (sum) r += p * A[i].sub, sum -= p * A[i].sub; //!!!
}
if (!find(D)) break;
}
for (int i=; i<=D; ++i) sumr[i] = sumr[i - ] + m - d[i]; // 剩余的前缀和
LL tmp = ;
for (int i=D; i>=; --i) del[i] = max(tmp - sumr[i], 0ll), tmp += d[i]; // 到第i天要删除的个数
for (int i=D; i>=; --i) {
ans[i] = Sum;
int now = del[i - ] - del[i]; // 从第i天到第i-1天,要减去多少蔬菜。
while (now) {
int mn = min(now, sk[Top]);
Sum -= 1ll * skw[Top] * mn;
now -= mn;
sk[Top] -= mn;
if (!sk[Top]) Top --;
}
}
for (int i=; i<=k; ++i) printf("%lld\n",ans[q[i]]);
return ;
}
4946: [Noi2017]蔬菜的更多相关文章
- 【刷题】BZOJ 4946 [Noi2017]蔬菜
Description http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf Solution 网上大部分都是并查集写法,但是有大神写了非并查集写 ...
- BZOJ.4946.[NOI2017]蔬菜(贪心 离线)
题目链接 因为有删除,考虑倒序处理某个p的询问. 那么每天删除xi的蔬菜就变成了每天运来xi的蔬菜.那么我们取当前最优的即可,早取晚取都一样,不需要留给后面取,还能给后面更优的留出空间. 这样就只需考 ...
- [NOI2017]蔬菜
[NOI2017]蔬菜 题目描述 大意就是有\(n\)种物品,第\(i\)个物品有\(c_i\)个,单价是\(a_i\).然后每天你可以卖出最多\(m\)个物品.每天结束后第\(i\)种物品会减少\( ...
- BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流
题目链接: [Noi2017]蔬菜 题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量), ...
- 【BZOJ4946】[NOI2017]蔬菜(贪心)
[BZOJ4946][NOI2017]蔬菜(贪心) 题面 BZOJ 洛谷 UOJ 题解 忽然发现今年\(NOI\)之前的时候切往年\(NOI\)的题目,就\(2017\)年的根本不知道怎么下手(一定是 ...
- bzoj4946: [Noi2017]蔬菜 神烦贪心
题目链接 bzoj4946: [Noi2017]蔬菜 题解 挺神的贪心 把第次买的蔬菜拆出来,记下每种蔬菜到期的日期,填第一单位蔬菜比其他的要晚 按价格排序后,贪心的往前面可以填的位置填就可以了.找可 ...
- [NOI2017]蔬菜 贪心
题面: [NOI2017]蔬菜 题解: 首先每天蔬菜会变质这点并不好处理,我们考虑让时间倒流,从后向前处理,这样的话就相当于每天都会得到一定量的蔬菜. 这样做有什么好处呢? 我们可以发现一个性质:如果 ...
- BZOJ4946 & 洛谷3826 & UOJ318:[NOI2017]蔬菜——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4946 https://www.luogu.org/problemnew/show/P3826 ht ...
- bzoj4946 Noi2017 蔬菜
题目描述 小 N 是蔬菜仓库的管理员,负责设计蔬菜的销售方案. 在蔬菜仓库中,共存放有nn 种蔬菜,小NN 需要根据不同蔬菜的特性,综合考虑各方面因素,设计合理的销售方案,以获得最多的收益. 在计算销 ...
随机推荐
- Ajax三级联动操作的js代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- ORACLE查询删除重复记录
比如现在有一人员表 (表名:peosons) 若想将姓名.身份证号.住址这三个字段完全相同的记录查询出来 复制代码 代码如下: select p1.* from persons p1,pers ...
- Yii 集成 PHPExcel读取Excel文件
PHPexcel官方下载以后,放入Yii的protected\extensions\phpexcel下面 try { spl_autoload_unregister(array('YiiBase', ...
- web.xml的加载过程是context-param >> listener >> fileter >> servlet
web.xml的加载过程是context-param >> listener >> fileter >> servlet
- 将数组打印到txt文件中
用print_r 将数组打印到txt文件中. 1.function save_log($content='', $file='app') { $logDir = './logs'; $now ...
- ECMAScript6 Generator & async
Generator Generator函数是一个状态机,执行后返回一个遍历器对象.调用遍历器对象的.next()函数获取下一个状态. Generator是一个普通的函数,函数内部使用yield关键字定 ...
- 解决FileUpload上传大文件报错
<system.webServer> <security> <requestFiltering> <requestLimits maxAllowedConte ...
- MATLAB PCHIP函数一阶求导分析
MATLAB PCHIP函数一阶求导分析 摘要:本文首先根据三次立方插值的一般表达式,得出分段三次立方插值时,每个小区间上的各次项系数.分析发现,三次项.二次项.一次项系数都与小区间端点处的一阶导数值 ...
- Python 学习笔记(九)Python元组和字典(三)
字典常用方法 copy() 返回一个字典的浅复制 示例:浅拷贝d.copy() 深拷贝引入import copy copy.deepcopy() >>> help(dict.co ...
- iOS11.2-11.3.1进行越狱及问题
设备环境:Electra.iOS11.13.1 PS:Electra最新版本进行越狱只支持11.14以下的版本.同时这是不完美越狱,每次重启手机都需要重新越狱,最后,由于Electra版本推出仓促,一 ...