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. 全屏轮播插件 fullPage.js应用(基础版兼容IE7, 背景图版兼容IE8)

    /** * fullPage 1.4.5 * https://github.com/alvarotrigo/fullPage.js * MIT licensed * * Copyright (C) 2 ...

  2. PHP------------正则表达式应用——实例应用

    正则表达式应用——实例应用     1.验证用户名和密码:("^[a-zA-Z]\w{5,15}$")正确格式:"[A-Z][a-z]_[0-9]"组成,并且第 ...

  3. HDU 1281 棋盘游戏 【二分图最大匹配】

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1281 题意概括: 有N*M大的棋盘,要在里面放尽量多的“车”,求最多能放的车的个数,和为了放最多的车有多 ...

  4. 如何创建.gitignore文件

    为什么要创建.gitignore文件? 因为.gitignore可以排除提交时携带的不必要文件,比如Java中的.class文件.同时还可以排除其他不想提交或者提交没这个必要的文件等等. 创建步骤如下 ...

  5. python-装饰器的简单使用

    一.介绍 首先我们先来看一个简单的例子,在基础平台中有一个home()和tv()函数,在业务平台中调用此函数时,给出了响应的打印内容: 基础平台: def home(): print('welcome ...

  6. JavaScript在浏览器中把文本保存为文件的方法

    JavaScript在浏览器中把文本保存为文件的方法 经过测试第二种方法可以保存更多的文本不至于卡死 var saveTextAsFile1 = function (text, fileName, s ...

  7. heatmap for arcgisjsapi

    在arcgis for js api 环境下使用heatmap插件. 由于最新的heatmap没有提供 for arcgisjsapi  插件,懒得研究新版本代码,所以这里用的还是老版本的heatma ...

  8. HDU 1053 Entropy(哈夫曼编码 贪心+优先队列)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1053 Entropy Time Limit: 2000/1000 MS (Java/Others)   ...

  9. GPIO 配置示例

    概述:学习STM32的GPIO configration /********************************************************************** ...

  10. type和 #define

    1.#define INT8U unsigned char   :  用INT8U代替unsigned char 2.typedef typedef int size; 此声明定义了一个int的同义字 ...