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]蔬菜的更多相关文章

  1. 【刷题】BZOJ 4946 [Noi2017]蔬菜

    Description http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf Solution 网上大部分都是并查集写法,但是有大神写了非并查集写 ...

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

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

  3. [NOI2017]蔬菜

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

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

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

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

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

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

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

  7. [NOI2017]蔬菜 贪心

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

  8. BZOJ4946 & 洛谷3826 & UOJ318:[NOI2017]蔬菜——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4946 https://www.luogu.org/problemnew/show/P3826 ht ...

  9. bzoj4946 Noi2017 蔬菜

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

随机推荐

  1. 使用redux开发的简单步骤

    一.安装redux包 npm install redux --save 二.根据APP数据结构或者后台请求的数据结构拟定state的大致结构. 可以把state写成一个对象字面量,放在reducer文 ...

  2. hdu-2619 Love you Ten thousand years

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2619 题目大意: 求出小于n的数的个数,满足ki mod n,1≤i≤n是模n的完全剩余系 解题思路 ...

  3. Swift编程语言学习1.1——常量与变量

    常量和变量把一个名字(比方maximumNumberOfLoginAttempts或者welcomeMessage)和一个指定类型的值(比方数字10或者字符串"Hello")关联起 ...

  4. Yii2.0 请求

    1.获取请求参数 $request = Yii::$app->request; $get = $request->get(); // 等价于:$get = $_GET; $id = $re ...

  5. 17、配置嵌入式servlet容器(1)

    SpringBoot默认使用Tomcat作为嵌入式的Servlet容器 1).如何定制和修改Servlet容器的相关配置         1.修改和server有关的配置            (Se ...

  6. iOS之序列化与反序列化

    所谓的序列化和反序列化就是将数据结构或对象和二进制串之间相互转换的过程: 本人的理解是当你于写数据需要本地存储时,即将你的数据写到硬盘上的时候,你就必须对他进行序列化,转换成二进制文件,从而便于在磁盘 ...

  7. C51 单片机的中断号以及中断向量

    1.外部中断0. 1:分别由引脚/INT0./INT1的电平信号引起. 2.定时/计数器0.1:分别由T0. T1的溢出引起. 3.串行口发送.接收:发送完一个字节或接收到一个字节引起. 上述共5个中 ...

  8. Unity 游戏框架搭建 (二十三) 重构小工具 Platform

    在日常开发中,我们经常遇到或者写出这样的代码 var sTrAngeNamingVariable = "a variable"; #if UNITY_IOS || UNITY_AN ...

  9. 三、Hadoop 的 API

    1.环境搭建 <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop- ...

  10. JAVA给你讲它的故事

    计算机语言如果你将它当做一个产品,就像我们平时用的电视机.剃须刀.电脑.手机等, 他的发展也是有规律的. 任何一个产品的发展规律都是:向着人更加容易使用.功能越来越强大的方向发展. 那么,我们的计算机 ...