【贪心+堆/模拟费用流增广】BZOJ4946 [NOI2017]蔬菜
一道思路很好的题,因为篇幅太长赶时间,以下多数转自这里
【题目】
定义了一种蔬菜为: a i , s i , c i , x i a_i,s_i,c_i,x_i ai,si,ci,xi,有 n n n种蔬菜
意思是蔬菜的价格为 a i a_i ai,第一份卖出时价格为 a i + s i a_i+s_i ai+si,一共有 c i c_i ci份,每天会有 x i x_i xi份过期;每天最多卖出 m m m份蔬菜,多组输入天数 d d d依次最大化收入。
n , m , d , T ≤ 1 0 5 n,m,d,T\leq 10^5 n,m,d,T≤105
【解题思路】
首先有一个费用流的做法是这样子的:首先对于蔬菜拆点,每一天拆出一个点,因为蔬菜可以购买的量逐渐递减,因此每一天向下一天连接流量为当前天减少 d d d的边,费用为 0 0 0,然后考虑把蔬菜卖出去,那么就是从一个蔬菜拆出来的某一天向汇点连边,因为限制每天购买的总量,所以再对于每一天的购买的蔬菜拆一个点,然后这一天的每一个蔬菜向这个点连容量为 i n f inf inf,费用为蔬菜费用的边,再从这个点向汇点连容量为 m m m,费用 为 0 为0 为0的边。显然源点向每个蔬菜的第一天连容量为蔬菜数量,费用为 0 0 0的边,至于第一次购买产生的额外贡献,我们把连的那条边拆出一个单位来,再额外链接一下容量为 1 1 1,费用为第一次购买产生的额外贡献的边。这样子连边就好了。
跳出来,往正解的方面想。
显然不难发现一个 O ( n Q ) O(nQ) O(nQ)的贪心,蔬菜会逐渐减少很不好做,我们倒过来,反过来考虑每一天,那么蔬菜的数量变成了每一天都增加每种蔬菜一定量,然后我们需要倒着买蔬菜就好了。可能需要数据结构什么的维护一下,但是大致的复杂度就是上述的东西。
我们现在再正着考虑,假设我们知道我们在 p p p天的时候的最优解中,买了哪些蔬菜,那么我们可以很容易的得到 p − 1 p-1 p−1天的答案,显然只需要把利润最小的那 m m m个蔬菜给去掉就好了,因为第 p − 1 p-1 p−1天可以购买的蔬菜不会少于第 p p p天,在第 p p p天能够买到的,在 p − 1 p-1 p−1天也一定能够买到。
前面说的不是很清楚,现在考虑如何求解第 p p p天的答案。我们既然是增加蔬菜,那么这个操作很容易维护,只需要搞一个堆出来,然后每次把当前所拥有的所有蔬菜全部拿出来贪心取就好了,稍微注意一下第一次选产生的额外贡献的细节就好。然后考虑如何递推回去,还是拿一个堆维护,同理注意一下第一次选产生的额外贡献。
既然这么讲了贪心怎么写,是不是觉得其实这就是一个模拟费用流的过程啊,倒推回去就是一个退流的过程,正推的贪心,显然每天只有那么几条路径,用堆维护等价于跑费用流。
复杂度 O ( n l o g n + q m ( l o g n + l o g q ) ) O(nlogn +qm(log\ n+log\ q)) O(nlogn+qm(log n+log q))
【参考代码】
#include<bits/stdc++.h>
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
using namespace std;typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,P=1e5;
int n,m,Q,sum;
int used[N],vis[N];
ll ans[N];
vector<int>d[N];
stack<pii>s;
priority_queue<pii>q;int read()
{int ret=0;char c=getchar();while(!isdigit(c)) c=getchar();while(isdigit(c)) ret=ret*10+(c^48),c=getchar();return ret;
}struct data
{int a,s,c,x;void rd(){a=read();s=read();c=read();x=read();}
}a[N];int main()
{#ifndef ONLINE_JUDGEfreopen("BZOJ4946.in","r",stdin);freopen("BZOJ4946.out","w",stdout);
#endifn=read();m=read();Q=read();for(int i=1;i<=n;++i) a[i].rd();for(int i=1;i<=n;++i) if(!a[i].x) d[P].pb(i); else d[min(P,(a[i].c+a[i].x-1)/a[i].x)].pb(i);for(int i=P;i;--i){for(int j=0,id;j<(int)d[i].size();++j) id=d[i][j],q.push(mkp(a[id].a+a[id].s,id));for(int j=m;j && !q.empty();){int w=q.top().fi,v=q.top().se;q.pop();if(!vis[v]){vis[v]=1;ans[P]+=w;++used[v];--j;if(a[v].c>1) q.push(mkp(a[v].a,v));}else{int res=min(j,a[v].c-used[v]-(i-1)*a[v].x);ans[P]+=(ll)res*w;used[v]+=res;j-=res;if(used[v]^a[v].c) s.push(mkp(a[v].a,v));}}while(!s.empty()) q.push(s.top()),s.pop();}while(!q.empty()) q.pop();for(int i=1;i<=n;++i) sum+=used[i];for(int i=1;i<=n;++i) if(used[i]==1) q.push(mkp(-a[i].s-a[i].a,i));else if(used[i]) q.push(mkp(-a[i].a,i));for(int i=P-1;i;--i){ans[i]=ans[i+1];while(sum>i*m && !q.empty()){int w=-q.top().fi,v=q.top().se;q.pop();if(used[v]>1){int res=min(sum-i*m,used[v]-1);used[v]-=res;sum-=res;ans[i]-=(ll)res*w;if(used[v]==1) q.push(mkp(-a[v].a-a[v].s,v));else q.push(mkp(-a[v].a,v));}else --sum,--used[v],ans[i]-=w;}}while(Q--) printf("%lld\n",ans[read()]);return 0;
}
【总结】
niubi
【贪心+堆/模拟费用流增广】BZOJ4946 [NOI2017]蔬菜相关推荐
- 【贪心 / 线段树模拟费用流增广】BZOJ4977 [Lydsy八月月赛] 跳伞求生
[题目] 原题地址 有nn个队友和mm个敌人,每个队友有一个攻击力aia_i,每个敌人有攻击力bib_i和价值cic_i.你可以选择若干个队友,每个队友ii分别去怼一个敌人jj,当ai>bja_ ...
- UOJ #455 [UER #8]雪灾与外卖 (贪心、模拟费用流)
题目链接 http://uoj.ac/contest/47/problem/455 题解 模拟费用流,一个非常神奇的东西. 本题即为WC2019 laofu的讲课中的Problem 8,经典的老鼠进洞 ...
- [UOJ455][UER #8]雪灾与外卖——堆+模拟费用流
题目链接: [UOJ455]雪灾与外卖 题目描述:有$n$个送餐员(坐标为$x_{i}$)及$m$个餐厅(坐标为$y_{i}$,权值为$w_{i}$),每个送餐员需要前往一个餐厅,每个餐厅只能容纳$c ...
- UOJ #455.【UER #8】雪灾与外卖 堆模拟费用流
题意 有n个人和m家商店,每个人都要买一道菜.第i个人的坐标是a[i],第j家商店的坐标是y[i],有c[i]道菜且每道菜价格为w[i],每个人还要花费其到商店距离的路费,问最小花费. n,m≤105 ...
- BZOJ3291Alice与能源计划——匈牙利算法+模拟费用流
题目描述 在梦境中,Alice来到了火星.不知为何,转眼间Alice被任命为火星能源部长,并立刻面临着一个严峻的考验.为 了方便,我们可以将火星抽象成平面,并建立平面直角坐标系.火星上一共有N个居民点 ...
- BZOJ 4946: [Noi2017]蔬菜 模拟费用流
title BZOJ 4946 LUOGU 3826 简化题意: 定义了一种蔬菜为:\(ai,si,ci,xi\),意思是蔬菜的价格为 \(a_i\),第一份卖出时价格为 \(a_i+s_i\),一共 ...
- BZOJ 5326 [JSOI2017]博弈 (模拟费用流、线段树)
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=5326 题解 终于成为第8个A掉这题的人--orz tzw神仙早我6小时 本以为这东西常数 ...
- BZOJ 1920 Luogu P4217 [CTSC2010]产品销售 (模拟费用流、线段树)
题目链接 (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=1920 (luogu) https://www.luogu.org/prob ...
- BZOJ 4849 [NEERC2016] Mole Tunnels (模拟费用流)
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4849 题解 其实也是模拟费用流,但是这道题和一般的题目不一样,这道题是在一个完全二叉树上 ...
最新文章
- 【非专业评测】发蜡、发膏、发泥、发油、啫喱、发膜、发胶、干胶、发棒、摩丝
- Mac下使用crontab来实现定时任务
- Arduino(新手之路1)
- Swift与C++混编 OpenCV初体验 图片打码~
- 【PHP发展史】PHP5.2 到 PHP5.6 中新增的功能详解
- 解决MySQL查询数据不一致诟病
- jenkins搭建_如何搭建移动端自动化测试平台?没错,就用Jenkins!
- 使用ASP.NET Core,JavaScript,PostegreSql和ChartJs的动态仪表板Web应用程序
- jvm_tool jconsole/ jprofiler/ JProbe/ VirtualVm/ TPV/ YourKit/ ITCAM/ MAT/ MDD4J
- Hive学习笔记(二)——数据模型
- 基于Thinkphp开发的网页点餐收银系统SAAS模式
- Mybatis generator 生成xml文件时覆盖原文件
- CS信息系统建设和服务认证都有哪些等级?系统集成企业如何评估申报CS认证等级?
- 服装标准中纰裂试验方法的比较与探讨
- 2. Spring Boot使用Apache Curator实现分布式锁(可重入排它锁)「第四章 ZooKeeper Curator应用场景实战」「架构之路ZooKeeper理论和实战」
- 购物车二级列表联动以及价格计算
- 支付宝余额提现收手续费了
- Google map地图限制显示区域、拖拽范围
- 服务器带宽什么意思?服务器带宽多少合适?
- 科技公司的域名大战!
热门文章
- 分享88个HTML旅游交通模板,总有一款适合您
- 如何写一封稍微像样的求职邮件
- 怎样删除微信朋友圈的内容?超简单的方法免费分享!
- 碳中和推动第四次工业革命
- windows设置CPU主频
- 基于中国剩余定理的秘密共享方案(miracl库)
- HCIP路由交换的三门考试
- 消除VMware启动虚拟机时的floppy0提示的方法
- 注意BeanPostProcessor启动时对依赖Bean的“误伤”陷阱(is not eligible for getting processed by all...)
- windows Bat 批命令 教程