「NOI2017」蔬菜

首先考虑流

可以从 \(s\) 流入表示得到蔬菜,流出到 \(t\) 表示卖出蔬菜,给每个蔬菜拆点,并给它它每天应得的蔬菜。

但是我们没办法直接给,注意到如果把变质看成得到并可以留给上一天,我们每天就可以得到变质的蔬菜并获得从后一天没用完的蔬菜,这就是建图的大体思路。

然后你发现这个东西需要对询问天数动态加点,加点后发现需要退流,可以暴力退 \(m\) 的流,复杂度是正确的。

期望得分 \(60\) 分

然后研究一下,发现退流是没有必要的,也就是说第 \(i\) 天选择的蔬菜一定是 第 \(i+1\) 天的子集

然后你可以写的简单一点。


考虑实际上,费用流的过程是可以模拟的,或者直接从贪心出发。

最后一天的选择集合是确定的,并且选择集合只会扩大,不会缩小,然后问题其实就变成了模拟。

你只需要拿一个堆维护当前可选的蔬菜的集合(注意,蔬菜的大小在外面维护即可)

对于一血,可以拆成新的一个蔬菜,也可以在进堆的时候特判

然后可以对每个询问暴力模拟,得到复杂度 \(O(nmq\log n)\) 的做法

期望得分 \(80\) 分


然后注意到第 \(i\) 天可以从第 \(i+1\) 天进行递推

维护一个第 \(i+1\) 天的买的集合,如果集合大小大于 \(mi\) ,就删掉小的删到 \(mi\)

复杂度 \(O(nm\log n)\) ,期望得分 \(100\) 分


Code:

#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#define ll long long
using std::min;
using std::max;
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
//#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
#define gc() getchar()
template <class T>
void read(T &x)
{
int f=0;x=0;char c=gc();
while(!isdigit(c)) f|=c=='-',c=gc();
while(isdigit(c)) x=x*10+c-'0',c=gc();
if(f) x=-x;
}
const int N=2e5+10;
int n,m,k,a[N],s[N],c[N],x[N];
std::vector<int> seg[N];
struct node
{
int id,c;
node(){}
node(int a,int b){id=a,c=b;}
bool friend operator <(node a,node b){return a.c<b.c;}
};
std::priority_queue <node> q;
int sta[N],tot,yuu[N*10],sell[N],vis[N],mxt;
ll ans[N];
int main()
{
//freopen("vegetables2.in","r",stdin);
//freopen("vegetables2.out","w",stdout);
read(n),read(m),read(k);
for(int i=1;i<=n;i++)
{
read(a[i]),read(s[i]),read(c[i]),read(x[i]);
//单位收益,一血收益,总库存,每天变质
if(x[i]) mxt=max(mxt,(c[i]-1)/x[i]+1);
}
mxt=min(mxt,100000);
if(!mxt) mxt=100000;
mxt+=5000;
for(int i=1;i<=n;i++)
{
if(x[i]) seg[min(mxt,(c[i]-1)/x[i]+1)].push_back(i);
else seg[mxt].push_back(i);
}
for(int sel,i=mxt;i;i--)
{
for(int j=0;j<seg[i].size();j++)
{
int id=seg[i][j];
q.push(node(id,a[id]+s[id]));
}
int lim=m;
while(lim&&!q.empty())
{
int now=q.top().id;
q.pop();
if(!vis[now])
{
--lim;
ans[mxt]+=a[now]+s[now];
++sell[now];
if(sell[now]!=c[now]) q.push(node(now,a[now]));
yuu[++yuu[0]]=a[now]+s[now];
vis[now]=1;
}
else
{
sel=min(lim,c[now]-x[now]*(i-1)-sell[now]);
sell[now]+=sel;
lim-=sel;
if(sell[now]!=c[now]) sta[++tot]=now;
ans[mxt]+=1ll*a[now]*sel;
for(int j=1;j<=sel;j++) yuu[++yuu[0]]=a[now];
}
}
for(int j=1;j<=tot;j++) q.push(node(sta[j],a[sta[j]]));
tot=0;
}
std::sort(yuu+1,yuu+1+yuu[0]);
for(int j=1,i=mxt;i;i--)
{
ans[i-1]=ans[i];
while(yuu[0]-j+1>(i-1)*m) ans[i-1]=ans[i-1]-yuu[j++];
}
for(int p,i=1;i<=k;i++) read(p),printf("%lld\n",ans[min(p,mxt)]);
return 0;
}

2019.6.24

「NOI2017」蔬菜 解题报告的更多相关文章

  1. 「NOI2017」游戏 解题报告

    「NOI2017」游戏 \(d\)这么小,你考虑直接对\(d\)个东西暴力 枚举\(x\)为\(a\)或\(b\)(\(c\)就不用了,因为\(a,b\)已经包含\(c\))了,剩下的就是个\(2-s ...

  2. 「NOI2017」整数 解题报告

    「NOI2017」整数 有一些比较简单的\(\log^2n\)做法 比如暴力在动态开点线段树上维护每个位置为\(0\)还是\(1\),我们发现涉及到某一位加上\(1\)或者减去\(1\)实际上对其他位 ...

  3. 「ZJOI2016」旅行者 解题报告

    「ZJOI2016」旅行者 对网格图进行分治. 每次从中间选一列,然后枚举每个这一列的格子作为起点跑最短路,进入子矩形时把询问划分一下,有点类似整体二分 至于复杂度么,我不会阿 Code: #incl ...

  4. 「HNOI2016」树 解题报告

    「HNOI2016」树 事毒瘤题... 我一开始以为每次把大树的子树再接给大树,然后死活不知道咋做,心想怕不是个神仙题哦 然后看题解后才发现是把模板树的子树给大树,虽然思维上难度没啥了,但是还是很难写 ...

  5. 「HNOI2016」序列 解题报告

    「HNOI2016」序列 有一些高妙的做法,懒得看 考虑莫队,考虑莫队咋移动区间 然后你在区间内部找一个最小值的位置,假设现在从右边加 最小值左边区间显然可以\(O(1)\),最小值右边的区间是断掉的 ...

  6. 「HNOI2016」网络 解题报告

    「HNOI2016」网络 我有一个绝妙的可持久化树套树思路,可惜的是,它的空间是\(n\log^2 n\)的... 注意到对一个询问,我们可以二分答案 然后统计经过这个点大于当前答案的路径条数,如果这 ...

  7. 「HAOI2018」染色 解题报告

    「HAOI2018」染色 是个套路题.. 考虑容斥 则恰好为\(k\)个颜色恰好为\(c\)次的贡献为 \[ \binom{m}{k}\sum_{i\ge k}(-1)^{i-k}\binom{m-k ...

  8. 「HNOI2016」最小公倍数 解题报告

    「HNOI2016」最小公倍数 考虑暴力,对每个询问,处理出\(\le a,\le b\)的与询问点在一起的联通块,然后判断是否是一个联通块,且联通块\(a,b\)最大值是否满足要求. 然后很显然需要 ...

  9. 「SCOI2016」围棋 解题报告

    「SCOI2016」围棋 打CF后困不拉基的,搞了一上午... 考虑直接状压棋子,然后发现会t 考虑我们需要上一行的状态本质上是某个位置为末尾是否可以匹配第一行的串 于是状态可以\(2^m\)压住了, ...

随机推荐

  1. 测开之路七十一:监控平台之js

    监控平台的js //datetimepicker的初始化函数(主要是对选择时间的下拉框)function init_datetimepicker() { //初始化格式和规则 $('#start'). ...

  2. Jenkins+GitLab持续集成

    向GitLab提交代码之后自动触发Jenkins构建 https://baijiahao.baidu.com/s?id=1630678692475452408&wfr=spider&f ...

  3. 16/8/23_CSS自动换行

    转载:http://blog.csdn.net/ye987987/article/details/8011875   自动换行问题,正常字符的换行是比较合理的,而连续的数字和英文字符常常将容器撑大,挺 ...

  4. ECMAScript 2015 迭代器协议:实现自定义迭代器

    迭代器协议定义了一种标准的方式来产生一个有限或无限序列的值,并且当所有的值都已经被迭代后,就会有一个默认的返回值. 当一个对象只有满足下述条件才会被认为是一个迭代器:它实现了一个 next() 的方法 ...

  5. (appium+python)UI自动化_08_unittest编写测试用例

    前言 unittest是python自带的单元测试框架,类似于Junit(Java单元测试框架).支持自动化测试,可编写测试前置&后置条件,并且可批量运行测试用例并生成测试报告. 使用unit ...

  6. python 按二维数组的某行或列排序 (numpy lexsort)

    lexsort支持对数组按指定行或列的顺序排序:是间接排序,lexsort不修改原数组,返回索引. (对应lexsort 一维数组的是argsort a.argsort()这么使用就可以:argsor ...

  7. opencv部署服务器报错

    报错内容: ImportError: libSM.so.6: cannot open shared object file: No such file or directory 解决办法: sudo ...

  8. C++中使用CMake编译管理项目

    CMake是一个跨平台的Makefile生成工具,可以根据特定的规则生成相应的Makefile文件,并对C/C++源代码进行编译和管理. 有一篇博客介绍CMake的使用,比较通俗易懂,链接地址是:Cm ...

  9. 【五一qbxt】day7-1 引水入城

    [noip2010 洛谷p1514]引水入城 Before: 线段覆盖问题#1:(我们所需要的) 一个区间,若干条线段,现在求最少多少条线段覆盖满整个区间 区间长度8,可选的覆盖线段[2,6],[1, ...

  10. P4158[SCOI2009]粉刷匠

    题目描述 windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色. 每个格子最多只能被 ...