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. [cocos2d-x]-会动的精灵

    小鸟一直在扑翅膀的代码块: auto sprite = Sprite::create(); Animation *animation = Animation::create(); animation- ...

  2. UVa 1638 - Pole Arrangement(dp)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  3. thinkphp清除缓存

    前台 //清除缓存 $(function(){ $("#cache").click(function(){ layer.confirm('你确定要清除缓存吗?', {icon: 3 ...

  4. 2019.1.2 Spring管理事务的方式

    Spring管理事务的方式 1.编码式 1.将核心事务管理器配置到Spring容器 2.配置TransactionTemplate模版 3.将事务模版注入service 4.在Service中调用模版 ...

  5. SPOJ SUBXOR

    SPOJ SUBXOR 题意 给定一个由正整数构成的数组, 求 异或和小于k 的子序列的个数. 题解 假设答案区间为 [L, R], XOR[L, R] 等价于 XOR[1, L - 1] ^ XOR ...

  6. SQL SERVER 对权限的授予GRANT、拒绝DENY、收回REVOKE

    -----对用户member授权,允许其具有对数据表person的更新和删除的操作权限:GRANT UPDATE,DELETE ON personTO member WITH GRANT OPTION ...

  7. sql1999语法

    1.交叉连接 cross join 左右两个表进行组合,产生笛卡尔积累. 左边每一行分别于右表每一行数据匹配. 2.using using使用的前提是两个表右关联的字段需要对应,两个表的join查询. ...

  8. Spring知识点小结(三)

    一.aop的简介 aop:面向切面编程    aop是一种思想,面向切面编程思想,Spring内部提供了组件对aop进行实现    aop是在运行期间使用动态代理技术实现的思想    aop是oop延 ...

  9. 前端ajax的各种与后端交互的姿势

    前端中常常用的与后端交换数据的话,通常是要用到ajax这种方法的 但是交互的方式有很多种,很多取决于你后端的属性,我这儿主要列举我目前项目比较常用的两种方式 --一个是我们通用的web api和控制器 ...

  10. 针对jquery的ajax中的参数理解

    1. url 发送请求的地址.为空表示当前页. $.ajax({ type: "post", data: studentInfo, contentType: "appli ...