BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流
题目链接:
题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量),每卖出一个单位的蔬菜获得收益为$a_{i}$,第一次卖出一种蔬菜会得到$s_{i}$的额外收益,限制每天最多卖出$m$个单位的蔬菜,有$k$次询问,每次询问卖$p_{i}$天的最大收益。
因为每种蔬菜坏掉的部分是固定的,那么我们可以将每种蔬菜分成$\frac{c_{i}-1}{x_{i}}+1$类,第$i$类在第$i$天坏掉。那么对于本题就可以建出费用流模型:源点向每一天连边,容量为$m$,费用为$0$;第$i$天向第$i+1$天连边,容量为$INF$,费用为$0$;每一天向每种蔬菜这一天坏掉的那类连边,容量为这一类的数量,费用为$0$;每一类蔬菜向汇点连边,容量为这一类的数量,费用为$a_{i}$。最后在最后一天每一种蔬菜中取出一个容量新建一个点连向汇点,容量为$1$,费用为$a_{i}+s_{i}$。这样直接跑费用流会有$60pts$。我们观察一下这个图的特殊性质:只有蔬菜向汇点连的边有费用。因为每次增广一定是选取最长路,那么每次增广的路径就一定不会走有费用的反向边(即不会退流)。这也就说明对于$p=i$时选取的蔬菜一定是$p=i-1$时选取的蔬菜的父集(多选的那部分就是最便宜的那$m$个蔬菜)。那么我们可以模拟这个费用流的过程——每次选择当前能选的蔬菜中权值最大的。为了使当前的选择是可行的,设$f[i]$为在第$i$天及之前过期的蔬菜选取量,那么我们就要保证$\forall i,f[i]-i*m<=0$,即$max(f[i]-i*m)<=0$,这个东西我们用线段树来维护即可。那么我们现在的问题就是如何要让当前权值最大的蔬菜尽可能的多选,因为选择第$i$天过期的蔬菜会将所有$i\le j$的$f[j]$都$+1$。那么如果不能选后过期的就一定不能选先过期的,而不能选先过期的可能还能选后过期的,所以我们每次贪心地先选后过期的那部分。如果一次选择使$masx(f[i]-i*m)>0$,说明这种蔬菜剩下的都过期了,那么就撤销这次操作并在以后都不选这种蔬菜。那么我们只要用堆维护所有种类的蔬菜然后从第一天开始,每天贪心地选$m$个蔬菜并记录每天的答案在最后统一输出即可。特别注意$x_{i}=0$的蔬菜看作都在最后一天过期。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define pr pair<int,int>
#define lim 100010
using namespace std;
int c[100010];
int a[100010];
int s[100010];
int x[100010];
int n,m,k,z;
ll ans[100020];
priority_queue<pr>q;
int mx[400010];
int sum[400010];
ll res;
void pushup(int rt)
{
mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void pushdown(int rt)
{
if(sum[rt])
{
sum[rt<<1]+=sum[rt];
sum[rt<<1|1]+=sum[rt];
mx[rt<<1]+=sum[rt];
mx[rt<<1|1]+=sum[rt];
sum[rt]=0;
}
}
void build(int rt,int l,int r)
{
if(l==r)
{
mx[rt]=-l*m;
return ;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
void change(int rt,int l,int r,int L,int R,int v)
{
if(L<=l&&r<=R)
{
mx[rt]+=v;
sum[rt]+=v;
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
if(L<=mid)
{
change(rt<<1,l,mid,L,R,v);
}
if(R>mid)
{
change(rt<<1|1,mid+1,r,L,R,v);
}
pushup(rt);
}
bool judge(int id)
{
int t=x[id]?(c[id]-1)/x[id]+1:lim;
change(1,1,lim,t,lim,1);
if(mx[1]<=0)
{
return 1;
}
change(1,1,lim,t,lim,-1);
return 0;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&a[i],&s[i],&c[i],&x[i]);
q.push(make_pair(a[i]+s[i],i));
}
build(1,1,lim);
for(int i=1;i<=lim;i++)
{
int num=m;
while(num&&!q.empty())
{
int v=q.top().first;
int id=q.top().second;
q.pop();
if(!judge(id))continue;
res+=v,num--,c[id]--;
if(c[id])
{
q.push(make_pair(a[id],id));
}
}
ans[i]=res;
}
while(k--)
{
scanf("%d",&z);
printf("%lld\n",ans[z]);
}
}
BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流的更多相关文章
- 【BZOJ3252】攻略 DFS序+线段树(模拟费用流)
[BZOJ3252]攻略 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛> ...
- BZOJ4977[Lydsy1708月赛]跳伞求生——贪心+堆+模拟费用流
题目链接: 跳伞求生 可以将题目转化成数轴上有$n$个人和$m$个房子,坐标分别为$a_{i}$和$b_{i}$,每个人可以进一个他左边的房子,每个房子只能进一个人.每个房子有一个收益$c_{i}$, ...
- [UOJ455][UER #8]雪灾与外卖——堆+模拟费用流
题目链接: [UOJ455]雪灾与外卖 题目描述:有$n$个送餐员(坐标为$x_{i}$)及$m$个餐厅(坐标为$y_{i}$,权值为$w_{i}$),每个送餐员需要前往一个餐厅,每个餐厅只能容纳$c ...
- BZOJ4946 NOI2017蔬菜(贪心+堆)
容易想到一个费用流做法:将每种蔬菜拆成p种,对应p个过期时间,每一种向可以卖的时间连边,第一次卖的奖励算在最晚过期的一种里.对于天数动态加点.不过这样边数太多了,因为第i天能卖的第i-1天一定能卖,可 ...
- 模拟费用流 & 可撤销贪心
1. CF730I Olympiad in Programming and Sports 大意: $n$个人, 第$i$个人编程能力$a_i$, 运动能力$b_i$, 要选出$p$个组成编程队, $s ...
- 【CF280D】 k-Maximum Subsequence Sum ,线段树模拟费用流
昨天考试被教育了一波.为了学习一下\(T3\)的科技,我就找到了这个远古时期的\(cf\)题(虽然最后\(T3\)还是不会写吧\(QAQ\)) 顾名思义,这个题目其实可以建成一个费用流的模型.我们用流 ...
- Codeforces 280D k-Maximum Subsequence Sum [模拟费用流,线段树]
洛谷 Codeforces bzoj1,bzoj2 这可真是一道n倍经验题呢-- 思路 我首先想到了DP,然后矩阵,然后线段树,然后T飞-- 搜了题解之后发现是模拟费用流. 直接维护选k个子段时的最优 ...
- 【BZOJ3638】Cf172 k-Maximum Subsequence Sum 线段树区间合并(模拟费用流)
[BZOJ3638]Cf172 k-Maximum Subsequence Sum Description 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交 ...
- 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
随机推荐
- 我的微软最有价值专家(Microsoft MVP)之路
一.写在前面 2018年对我来说是幸运的一年,对我来说最幸运的事情有两个,一个是在离驾照考试过期还有一个月(报名之后一直没去考)终于拿到了我的驾照,还有一件事莫过于获得了微软MVP.期间,一直有朋友问 ...
- python--Numpy and Pandas 笔记01
博客地址:http://www.cnblogs.com/yudanqu/ 1 import numpy as np import pandas as pd from pandas import Ser ...
- android linux 传文件
EStrongs File Explorer 即: Es文件浏览器 网络 -> 远程管理器 设置 ->设置根目录 linux 使用浏览器访问即可.
- Python中IO概述
Python中的io模块是用来处理各种类型的I/O操作流.主要有三种类型的I/O类型:文本I/O(Text I/O),二进制I/O(Binary I/O)和原始I/O(Raw I/O).它们都是通用类 ...
- Python学习第十二篇——切片的使用
Python中使用函数切片可以创建副本,保留原本.现在给出如下代码 magicians_list = ['mole','jack','lucy'] new_lists = [] def make_gr ...
- Sagheer and Nubian Market CodeForces - 812C (二分)
On his trip to Luxor and Aswan, Sagheer went to a Nubian market to buy some souvenirs for his friend ...
- 关于XLL加载项动态加载、卸载的演示及XLL函数自定义类型注册的演示
1.在XLL中,把函数定义成不同的类型,在Excel中的实际效果也不同,具体如下: pxMacroType value ...
- Python_内置函数之zip
zip函数用于将可迭代的对象作为参数,将对象中的元素打包成一个个元祖,然后返回这些元祖组成的列表.如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同. l1 = [1, 2, 3] l2 ...
- 软件工程(FZU2015) 增补作业
SE_FZU目录:1 2 3 4 5 6 7 8 9 10 11 12 13 说明 张老师为FZU软件工程2015班级添加了一次增补作业,总分10分,deadline是2016/01/01-2016/ ...
- 福州大学软件工程1816 | W班 第8次作业[团队作业,随堂小测——校友录]
作业链接 团队作业,随堂小测--校友录 评分细则 本次个人项目分数由两部分组成(博客分满分40分+程序得分满分60分) 博客和程序得分表 评分统计图 千帆竞发图 总结 旅法师:实现了更新,导出,查询, ...