uoj318 [NOI2017]蔬菜 【贪心 + 堆 + 并查集】
题目链接
题解
以前看别人博客,在考场上用费用流做,一直以为这题是毒瘤网络流题
没想到竟然是贪心模拟题。。。
如果只有一个蔬菜呢?这就是一个经典的普及难度的贪心,正着推面临优先选择的困难,而逆着推由于不存在淘汰,所以可以贪心选最大的
首先\(s_i\)的限制很容易处理,只需将每一个蔬菜分出一个价值\(a_i + s_i\)且过期时间为该蔬菜最后一个的蔬菜
现在我们计算出每个蔬菜最晚放置的时间点,将每一天看做一个盒子,我们贪心地优先将价值大的蔬菜从它能放入的地方一直往前放
由于每个盒子最多放\(10\)个,我们用并查集合并相邻的放满的盒子,全部放置满只需\(O(10^5m)\)
但是这样对于每一个\(p\)都要算一次,实则不然,我们先算出最大的\(p\)的答案,发现前\(p - 1\)天能使用的蔬菜包含前\(p\)天能使用的蔬菜,我们用堆维护已放入的蔬菜,对于前\(p - 1\)天,我们只需把堆中的蔬菜减至\((p - 1)m\)即可
复杂度\(O(10^5mlogn)\)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<vector>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 200005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
priority_queue<LL,vector<LL>,greater<LL> > q;
LL cost[maxn],los[maxn],tot[maxn],E[maxn];
LL p[maxn],Pi = 100000,used[maxn],ans;
int n,m,K,N,pre[maxn],id[maxn];
inline int find(int u){return u == pre[u] ? u : pre[u] = find(pre[u]);}
inline bool cmp(const int& a,const int& b){
return cost[a] > cost[b];
}
void work(){
REP(i,N) id[i] = i;
REP(i,Pi) pre[i] = i; used[0] = m;
sort(id + 1,id + 1 + N,cmp);
LL sum,Out;
for (int i = 1; i <= N; i++){
int u = id[i],now;
if (u > n){
now = find(E[u]);
if (!now) continue;
used[now]++;
ans += cost[u];
q.push(cost[u]);
if (used[now] == m) pre[now] = now - 1;
}
else {
Out = 0; now = E[u];
for (; ; now--){
now = find(now);
if (!now) break;
sum = tot[u] - los[u] * (now - 1) - Out;
if (!sum && !los[u]) break;
else if (!sum) continue;
if (sum >= m - used[now]){
Out += m - used[now];
ans += cost[u] * (m - used[now]);
pre[now] = now - 1;
REP(j,m - used[now]) q.push(cost[u]);
used[now] = m;
}
else {
Out += sum;
used[now] += sum;
ans += cost[u] * sum;
REP(j,sum) q.push(cost[u]);
}
}
}
}
p[Pi] = ans;
for (int i = Pi - 1; i; i--){
while (q.size() > 1ll * m * i) ans -= q.top(),q.pop();
p[i] = ans;
}
}
int main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
N = n = read(); m = read(); K = read(); int s;
for (int i = 1; i <= n; i++){
cost[i] = read(); s = read(); tot[i] = read(); los[i] = read();
cost[++N] = cost[i] + s; tot[N] = 1; tot[i]--;
if (!los[i]) E[i] = E[N] = Pi;
else if (tot[i] / los[i] >= Pi) E[i] = E[N] = Pi;
else {
E[i] = tot[i] / los[i] + (tot[i] % los[i] != 0);
if (E[i] * los[i] > tot[i]) E[N] = E[i];
else E[N] = E[i] + 1;
}
}
work();
while (K--) printf("%lld\n",p[read()]);
return 0;
}
uoj318 [NOI2017]蔬菜 【贪心 + 堆 + 并查集】的更多相关文章
- Luogu 1525 【NOIP2010】关押罪犯 (贪心,并查集)
Luogu 1525 [NOIP2010]关押罪犯 (贪心,并查集) Description S城现有两座监狱,一共关押着N名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨 ...
- 【bzoj1455】罗马游戏 可并堆+并查集
题目描述 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人,每个人都是一个独立的团.最近举行了一次平面几何测试,每个人都得到了一个分数. 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻.他决定玩这样 ...
- NOI2017蔬菜(贪心)
小 N 是蔬菜仓库的管理员,负责设计蔬菜的销售方案. 在蔬菜仓库中,共存放有 n 种蔬菜,小 N 需要根据不同蔬菜的特性,综合考虑各 方面因素,设计合理的销售方案,以获得最多的收益. 在计算销售蔬菜的 ...
- BZOJ.4946.[NOI2017]蔬菜(贪心 离线)
题目链接 因为有删除,考虑倒序处理某个p的询问. 那么每天删除xi的蔬菜就变成了每天运来xi的蔬菜.那么我们取当前最优的即可,早取晚取都一样,不需要留给后面取,还能给后面更优的留出空间. 这样就只需考 ...
- [NOI2017]蔬菜 贪心
题面: [NOI2017]蔬菜 题解: 首先每天蔬菜会变质这点并不好处理,我们考虑让时间倒流,从后向前处理,这样的话就相当于每天都会得到一定量的蔬菜. 这样做有什么好处呢? 我们可以发现一个性质:如果 ...
- hdu 2480 贪心+简单并查集
Steal the Treasure Time Limit: 10000/6000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- BZOJ4699 树上的最短路(最短路径+dfs序+线段树+堆+并查集)
首先一般化的将下水道和塌陷看成一个东西.注意到在从源点出发的所有需要使用某条下水道的最短路径中,该下水道只会被使用一次,该下水道第一个被访问的点相同,且只会在第一个访问的点使用该下水道.这个第一个访问 ...
- bzoj 1455 可并堆+并查集
一个堆和一个并查集对应,并且满足并查集中所有没有死的人等于堆中的人 /************************************************************** Pr ...
- POJ-1456 Supermarket(贪心,并查集优化)
Supermarket Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10725 Accepted: 4688 Descript ...
随机推荐
- JavaScript学习笔记(六)—— 异步编码
第七章 异步编码 1 事件处理程序 处理程序:即网页加载完毕后将执行的代码,称回调函数或监听器: 包含:处理函数+window.onload=函数名; <script language=&qu ...
- Oracle之带参存储过程(存储过程中for循环调用存储过程)
--带参存储过程create or replace procedure testdate(v in number) is i number; begin i:=v; insert into test_ ...
- 炸!分享美团面试关于selenium的面试题
个人分类: 软件测试 编辑 在这个互联网技术快速迭代的时代,每个测试员都知道技术对于职业发展的重要性,那些技术好的测试员不仅薪资高,而且大多数集中在一线互联网企业工作,让人感觉非常高大上的同时,也想去 ...
- Git常用使用技巧
- 此随笔不是使用教材,使用教材参照git官方文档和相应博客 - 此随笔不是转载而来,涉及不少三方链接,再次表示感谢 - 此随便乃实践中碰到的问题,增加开发效率,干货满满 git 撤销某次提交的技巧: ...
- kafka handler
1.配置kafka 参数文件 在ogg主目录下有示例文件: [root@WH0PRDBRP00AP0013 ogg]# cd AdapterExamples/big-data/kafka/ [root ...
- javascript中的call(),apply(),bind()方法的区别
之前一直迷惑,记不住call(),apply(),bind()的区别.不知道如何使用,一直处于懵懂的状态.直到有一天面试被问到了这三个方法的区别,所以觉得很有必要总结一下. 如果有不全面的地方,后续再 ...
- 四则运算(window窗体程序)
我的第一个程序 忙活了半个下午做出来了,勉强可以见人,虽然还有些瑕疵,但是我也尽力了...... 我做的是一个能对0--10之间的整数进行四则运算的,题目的数据是程序自动生成的,而且程能接收用户输入的 ...
- BNUOJ 52303 Floyd-Warshall Lca+bfs最短路
题目链接: https://www.bnuoj.com/v3/problem_show.php?pid=52303 Floyd-Warshall Time Limit: 60000msMemory L ...
- c++中的函数重载
函数多态也称为函数重载. (1)函数重载指的是可以有多个同名的函数,因此对名称进行了重载. (2)函数重载的关键在于函数的参数列表,也称为函数特征标.如果两个函数的参数数目和参数类型相同,同时参数的排 ...
- Java Lock & Condition
/* jdk1.5以后将同步和锁封装成了对象. 并将操作锁的隐式方式定义到了该对象中, 将隐式动作变成了显示动作. Lock接口: 出现替代了同步代码块或者同步函数.将同步的隐式锁操作变成现实锁操作. ...