【题解】「NOIP2016」蚯蚓
题目大意:
一共有n只蚯蚓,每只蚯蚓有一个长度,并且蚯蚓会按每年q厘米的速度增长。现在每年选择一只最长的蚯蚓,将其按p的比例切成两半,被切的的蚯蚓这一年不能增长,问每年被切的蚯蚓的长度和m年后所有蚯蚓的长度(据题意只需输出部分结果)
题目分析:
看到这题首先想到的是使用堆来做(因为,切蚯蚓符合堆的查询极值、插入和删除)。但考虑到数据的范围(1<=n<=1051<=n<=10^51<=n<=105,0<=m<=7∗1060<=m<=7*10^60<=m<=7∗106),由于使用堆的时间复杂度为O(m*logn),其结果必然会导致超时,所以只有另辟蹊径。
再仔细观察,发现每年切最长的一只蚯蚓,说明切过的蚯蚓长度具有单调性,即先切的蚯蚓的左段一定大于等于后切蚯蚓的左段,先切蚯蚓的右段一定大于等于后切蚯蚓的右段。
以下为证明过程:为方便,设两只蚯蚓长度为a,b,切后的长度分别是a1,a2,b1,b2.
- a>=b
- 所以 ap>=bp,a-ap>=b-bp
- 因为切这两只蚯蚓的时候这两只蚯蚓都少增长了q厘米
- 所以可证a1>=b1,a2>=b2
因此我们可以想到这题可以使用普通队列来做,使复杂度降至O(m) - 使用3个队列分别保存没被切过的蚯蚓,被切过的蚯蚓左段,和被切过的蚯蚓右段
注意因为最开始给的蚯蚓数据并不是按照递减顺序,所以可以选择提前排序或者第一个队列使用优先队列 - 每次取出3个队列中最长的一只蚯蚓,将其切断都分别放入后两个数组,依此类推循环m次即可求出结果
- 还需要考虑蚯蚓的增长长度问题,由于每次除了被切的蚯蚓,其他所有的蚯蚓都在增长,所以只需要再从队列中取元素的时候加上(i-1)q,放回时减去iq的长度(因为被切的蚯蚓这年不增长,所以多减q厘米,具体实现参见程序)
#include<bits/stdc++.h>
using namespace std;const int inf=-0x3f3f3f3f;
int n,m,q,u,v,t,in[100005],delta;
double p;
queue<int> a,b,c;void read() {scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t);p=u*1.0/v;for(int i=1;i<=n;i++) {scanf("%d",&in[i]);}sort(in+1,in+1+n);for(int i=n;i>=1;i--) {a.push(in[i]);}
}
void work() {for(int i=1;i<=m;i++) {int x=inf,y,z,out;if(a.size()) x=a.front();if(i==1) {a.pop();x+=delta;out=x;b.push(int(x*p)-delta-q);c.push(x-int(x*p)-delta-q);}else {y=b.front(),z=c.front();if(x>=y&&x>=z) {a.pop();x+=delta;out=x;b.push(int(x*p)-delta-q);c.push(x-int(x*p)-delta-q);}else if(y>=x&&y>=z) {b.pop();y+=delta;out=y;b.push(int(y*p)-delta-q);c.push(y-int(y*p)-delta-q);}else {c.pop();z+=delta;out=z;b.push(int(z*p)-delta-q);c.push(z-int(z*p)-delta-q);}}if(i%t==0) printf("%d ",out);delta+=q;}
}
void print() {for(int i=1;i<=n+m;i++) {int x=inf,y=inf,z=inf,out;if(a.size()) x=a.front();if(b.size()) y=b.front();if(c.size()) z=c.front();if(x>=y&&x>=z) {out=x;a.pop();}else if(y>=x&&y>=z) {out=y;b.pop();}else {out=z;c.pop();}if(i%t==0) printf("%d ",out+delta);}
}
int main() {read();work();printf("\n");print();
}
【题解】「NOIP2016」蚯蚓相关推荐
- 「NOIP2016」天天爱跑步
小 C 同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一棵包含 s ...
- 【信息学竞赛真题! ! !】信息学竞赛人必看的「NOIP2011」铺地毯 题解(C++版)
Hi,朋友们.又见面了.上次我们做了一道美国题,这次我们来干一道"国产"题目 文章目录 A.题目描述 B.初步分析 如果使用二维数组-- C.改进算法 D.补充模块 1.喜闻见乐的 ...
- 「PKUSC2018」神仙的游戏 - 题解
「PKUSC2018」神仙的游戏 题意:给出一个01?串,其中?可以代替成为0或1,令 $ F(i) $ 表示是否存在长度为 $ i $ 的border,求 $ (F(1) \times 1 \tim ...
- 「SDOI2016」征途 题解
「SDOI2016」征途 先浅浅复制一个方差 显然dp,可以搞一个
- 一直学不明白的「递归」与「动态规划」原来这么简单
在学习「数据结构和算法」的过程中,因为人习惯了平铺直叙的思维方式,所以「递归」与「动态规划」这种带循环概念(绕来绕去)的往往是相对比较难以理解的两个抽象知识点. 程序员小吴打算使用动画的形式来帮助理解 ...
- AC日记——「HNOI2017」礼物 LiBreOJ 2020
#2020. 「HNOI2017」礼物 思路: A题进程: 一眼出式子->各种超时过不去->看题解明白还有fft这个东西->百度文库学习fft->学习dft->学习fft ...
- LOJ#2230. 「BJOI2014」大融合
LOJ#2230. 「BJOI2014」大融合 题目描述 小强要在$N$个孤立的星球上建立起一套通信系统.这套通信系统就是连接$N$个点的一个树.这个树的边是一条一条添加上去的. 在某个时刻,一条边的 ...
- 【每日一题】5月7日题目精讲 「火」皇家烈焰
链接: 「火」皇家烈焰 文章目录 题目描述 题解: 代码: 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: % ...
- 「BZOJ1485」[HNOI2009] 有趣的数列 (卡特兰数列)
「BZOJ1485」[HNOI2009] 有趣的数列 Description 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai ...
- 「hdu6608」Fansblog 威尔逊定理
「hdu6608」 Fansblog 今天回顾之前多校联赛的题目:Fansblog ,发现一件有趣的事情,快速积的时间复杂度,比普通*快多了,刚才一直Tle 在用了普通*,卧槽这也能T,当然也有乘法爆 ...
最新文章
- 为什么所有的React应用开头都有一行meta charset=utf-8语句?
- 读书笔记 --- [基础知识点] 小结3
- 377. 组合总和 Ⅳ golang 动态规划
- 2005精品书籍-go go go
- C++中lib和dll解析
- CUDA C中核函数(kernel)的编写及调用
- 求助!C++ 实践之引入外部头文件失败
- web 开发之js---理解并解决IE的内存泄漏方式
- Android studio 0.5.0 注意事项
- java实现栈的方法
- 机房收费系统个人重构—图(文档)
- 2008 R2修复光盘_翻录和刻录CD媒体文件,使用Windows 10操作系统如何刻录光盘
- 刘备当年是如何面试诸葛亮的?
- MonoGRNet: A Geometric Reasoning Network for Monocular 3D Object Localization
- 让洁净煤保障群众温暖过冬
- oracle--函数COALESCE
- NAN、QNAN、 SNAN、 IND、 INF
- “不为圣贤,便为禽兽。莫问收获,但问耕耘”
- UG编程入门实战详解,带你快速了解UG编程的实现
- 【高等数学】—基础求导公式、等价无穷小转换公式