题干

本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3。蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓。蛐蛐国里现在共有n只蚯蚓(n为正整数)。每只蚯蚓拥有长度,我们设第i只蚯蚓的长度为a_i(i=1,2,...,n),并保证所有的长度都是非负整数(即:可能存在长度为0的蚯蚓)。每一秒,神刀手会在所有的蚯蚓中,准确地找到最长的那一只(如有多个则任选一个)将其切成两半。神刀手切开蚯蚓的位置由常数p(是满足0<p<1的有理数)决定,设这只蚯蚓长度为x,神刀手会将其切成两只长度分别为[px]和x-[px]的蚯蚓。特殊地,如果这两个数的其中一个等于0,则这个长度为0的蚯蚓也会被保留。此外,除了刚刚产生的两只新蚯蚓,其余蚯蚓的长度都会增加q(是一个非负整常数)。蛐蛐国王知道这样不是长久之计,因为蚯蚓不仅会越来越多,还会越来越长。蛐蛐国王决定求助于一位有着洪荒之力的神秘人物,但是救兵还需要m秒才能到来......(m为非负整数)蛐蛐国王希望知道这m秒内的战况。具体来说,他希望知道:m秒内,每一秒被切断的蚯蚓被切断前的长度(有m个数)m秒后,所有蚯蚓的长度(有n+m个数)。蛐蛐国王当然知道怎么做啦!但是他想考考你......

Input

第一行包含六个整数n,m,q,u,v,t,其中:n,m,q的意义见问题描述;

u,v,t均为正整数;你需要自己计算p=u/v(保证0<u<v)t是输出参数,其含义将会在输出格式中解释。

第二行包含n个非负整数,为ai,a2,...,an,即初始时n只蚯蚓的长度。

同一行中相邻的两个数之间,恰好用一个空格隔开。

保证1<=n<=10^5,0<m<7*10^6,0<u<v<10^9,0<=q<=200,1<t<71,0<ai<10^8。

Output

第一行输出[m/t]个整数,按时间顺序,依次输出第t秒,第2t秒,第3t秒……被切断蚯蚓(在被切断前)的长度。

第二行输出[(n+m)/t]个整数,输出m秒后蚯蚓的长度;需要按从大到小的顺序依次输出排名第t,第2t,第3t……的长度。

同一行中相邻的两个数之间,恰好用一个空格隔开。即使某一行没有任何数需要 输出,你也应输出一个空行。

请阅读样例来更好地理解这个格式。

Example

in:

3 7 1 1 3 1

3 3 2

out:

3 4 4 4 5 5 6

6 6 6 5 5 4 4 3 2 2

又要开始扯淡了...

完整的思路来源于这里:[膜拜大佬]: https://www.cnblogs.com/ljh2000-jump/p/6184271.html

很不错的博客,包括基本的一步步的思路和解释都写出来了。唯一接受不能的是代码,没有注释还好说,为毛要把所有循环都写在一行里啊!(╯‵□′)╯︵┻━┻

大家如果对部分分的实现有想法可以直接去看上面那篇博客,我这里直接着重介绍正解。(个人还是推荐大家去看一看的,毕竟真正考试的时候哪有这么容易想到正解╮(╯▽╰)╭)

首先,每次都要取出一个最大值来进行操作,我们第一时间想到的就是堆,当然这么大的数据我们能手写单调队列还是手写而且上面的博客里也提到了这点,况且对这道题而言也多费不了多少事。然后就是还有一个给所有蚯蚓都加上q的操作,直接加到每一个蚯蚓身上显然时间上不允许,所以我们考虑开一个全局的tmp储存蚯蚓长度的总改变量,在堆里面只储存原始值(当然我们肯定是要更新队首元素的),每次更新时取出最大值,加上tmp,得到真实值,算出两个新元素值,tmp加上q,两个新元素值减去tmp,丢入堆中。

那么我们最后为什么要用三个队列分别储存原始值、p×x和x-p×x呢?因为这三个队列各自具有单调性。

对于单调性的研究,我们能得出这个队列一定是不上升的(蚯蚓长度可能为0,所以不是单调递减),我们可以考虑如下:(这里直接考虑q为自然数的情况,省去了先从q=0考虑开始的步骤)

我们假设某一时刻队列中有一个最大值A,有一个值B,根据定义,B肯定是小于等于A的,此时A被切割成两个部分。然后经过了N轮切割,轮到B被切割了,我们再假设B被切割出来的部分比先前A切割出来的部分大,那么有:

  • A×p+N×q<(B+N×q)×p(只考虑乘以p的部分)
  • 那么展开一下得:A×p+N×q<B×p+N×q×p
  • 我们知道A>=B,而且p<1,那么显然上面的式子是矛盾的,则反证法可证出队列一定不上升

其实我们换个角度来理解,我们一直都在对最大的那条切切切,虽然从整体上看我们切去的肯定不如增长的长度多,但是增长的长度那是针对所有蚯蚓而言的啊。每条蚯蚓都是在同时增长相同的值,那么说明他们之间的相对长度都是永远不变的(假如我们不去切他),那么我们现在去切蚯蚓,即使不会使长度更短,起码也不会更长吧。

所以,根据上面的结论,我们分为三个单调队列来分别存储:原队列、p×x和x-p×x,这三个队列每单独一个拿出来都是保证不上升的。

小提醒:

由于题目中不是直接给出的p,而是通过给出分子分母要求我们自己计算p,来降低精度误差。在乘的时候需要开一个long long的临时变量,除完之后再转成int就可以了。其余的均可只开int。

ps:写的还是太着急了,有空我再更新更新。。。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
const int maxn=7000000+10;
const ll inf=1ll<<60;
int m,n,q,t,tmp;
int qu[3][maxn],head[3],tail[3];//维护三个单调队列
ll u,v;
bool Cmp(int a,int b){
return a>b;
}
void Init(){
scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t);
for(int i=1;i<=n;i++){
scanf("%d",&qu[0][i]);
}
sort(qu[0]+1,qu[0]+1+n,Cmp);
tmp=0;
head[0]=head[1]=head[2]=1;
tail[0]=n;//一开始所有蚯蚓都在第1队列里,我们把px都放入第2队列,x-px都放入第3队列
tail[1]=tail[2]=0;
}
void Solve(){
ll now;
int from,l1,l2,out=0;
bool flag=1;
for(int i=1;i<=m;i++){
now=-inf;//选取三个队列中的最大值
from=-1;
for(int j=0;j<=2;j++)
if(head[j]<=tail[j]){
if(qu[j][head[j]]>now){//更新最大值
now=qu[j][head[j]];
from=j;
}
}
now+=tmp;
out++;
if(out==t){//保证在t的整数倍输出
if(!flag) printf(" ");
flag=0;
printf("%lld",now);
out=0;
}
l1=now*u/v;
l2=now-l1;
head[from]++;
tmp+=q;
l1-=tmp,l2-=tmp;
qu[1][++tail[1]]=l1;//添加队列元素
qu[2][++tail[2]]=l2;
//printf("after %d s cut,tmp=%d\n",i,tmp);
}
printf("\n"); //以下为第二行输出
m+=n;out=0;flag=true;
for(int i=1;i<=m;i++) {
now=-inf; from=-1;
for(int j=0;j<3;j++)
if(head[j]<=tail[j]){
if(qu[j][head[j]]>now){
now=qu[j][head[j]];
from=j;
}
}
now+=tmp;
out++;
if(out==t) {
if(!flag) printf(" ");
flag=false;
printf("%lld",now);
out=0;
}
head[from]++;
}
}
int main(){
Init();
Solve();
return 0;
}

[Noip2016]蚯蚓 (单调队列)的更多相关文章

  1. [noip2016]蚯蚓<单调队列+模拟>

    题目链接:https://vijos.org/p/2007 题目链接:https://www.luogu.org/problem/show?pid=2827#sub 说实话当两个网站给出AC后,我很感 ...

  2. luogu 2827 蚯蚓 单调队列/优先队列

    易知可利用优先队列选取最大值: 但是通过分析可知,先取出的蚯蚓分开后仍然要比后分的长,所以可直接利用单调队列找队头即可,分三个单调队列,分别找未切割,切割,切割2三种情况 #include<bi ...

  3. 洛谷P2827 蚯蚓(单调队列)

    题意 初始时有$n$个蚯蚓,每个长度为$a[i]$ 有$m$个时间,每个时间点找出长度最大的蚯蚓,把它切成两段,分别为$a[i] * p$和$a[i] - a[i] * p$,除这两段外其他的长度都加 ...

  4. 【BZOJ】4721: [Noip2016]蚯蚓 / 【洛谷】P2827 蚯蚓(单调队列)

    Description 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮 ...

  5. [Noip2016]蚯蚓 D2 T2 队列

    [Noip2016]蚯蚓 D2 T2 Description 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯 ...

  6. NOIP2016-D2-T2 蚯蚓(单调队列)

    构建三个单调队列(用STL),分别储存未切的蚯蚓,切后的第一段,切后的第二段,即可简单证明其单调性. 证明:设$q$为单调队列$\because a_1 \geqslant a_2 \geqslant ...

  7. 【uoj264】 NOIP2016—蚯蚓

    http://uoj.ac/problem/264 (题目链接) 题意 n条蚯蚓,时间为m.每单位时间要可以将最长的蚯蚓切成len/2和len-len/2两份,长度为0的蚯蚓不会消失,因为每单位时间所 ...

  8. BZOJ4721 [Noip2016]蚯蚓

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  9. [NOIp2016] 蚯蚓

    类型:单调队列 传送门:>Here< 题意:有$N$只蚯蚓,每秒都会伸长$q$.每一次都会有人选出最长的一条切成两半,长度分别是$\left \lfloor px \right \rflo ...

随机推荐

  1. 【JAVA习题十九】利用递归方法求5!。

    package erase; public class 用递归法求5的阶乘 { public static void main(String[] args) { // TODO Auto-genera ...

  2. 05.Django-form表单与请求的生命周期

    Django中请求的生命周期 HTTP请求及服务端响应中传输的所有数据都是字符串 步骤 用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务器 url经过wsgi和中间件,到达路由映射表,在 ...

  3. 运行npm run start 提示primordials is not defined

    下载https://github.com/ant-motion/editor-list 执行 npm install npm start gulp构建时报错. 原因:安装gulp版本与node版本不兼 ...

  4. CentOS7.6操作系统安装实例以及Linux版本、哲学思想介绍

    Linux起源1991年的10月5日,Torvalds在comp.os.minix新闻组上发布消息,正式向外宣布他自行编写的完全自由免费的内核诞生(Freeminix-like kernel sour ...

  5. .NetCore对接各大财务软件凭证API——用友系列(2)

    一. 前言 今天我们继续来分析用友系列的第二个产品--U8Cloud2.5 ,apilink方式的API.官网的API文档地址如下:U8API文档 因为我们主要是凭证对接,所以使用到的模块有总账.基础 ...

  6. spring-framework 源码的下载与构建

    整体流程: 本地环境准备 找到源码地址并拉取到本地 根据IDE工具查看源码中提供的不同的安装说明并具体操作 构建会出现的的错误及解决 一.本地环境准备 spring-framework 源码使用gra ...

  7. Java学习之IO流及网络编程

    一.字节 1.1字节输入流(java.io.InputStream) ​ 此抽象类是表示字节输入流的所有类的超类 1.1.1定义了所有子类共性的方法: ​ int read() 从输入流中读取数据的下 ...

  8. JPA 中 find() 和 getReference() 的区别

    在查询的时候有两个方法:find()和getReference(),这两个方法的参数以及调用方式都相同.那么这两个方法有什么不一样的呢? find()称为 立即加载,顾名思义就是在调用的时候立即执行查 ...

  9. macos的两个快捷键和一个小tip

    学校的linux协会介绍了一个免费的light轻量级加速器,昨天晚上十点左右的时候着手研究,发现其实就是一个代理服务器.在配置这个代理服务器的时候碰到了一些困难并最终都解决了.下面记录一下配置过程学到 ...

  10. Linux下,如何监控某个进程到底向哪个地址发起了网络调用

    Linux下,如何监控某个进程到底向哪个地址发起了网络调用 有时候,有些应用,比如idea,你发起某个操作时,其底层会去请求网络,获取一些数据. 但是不知道,请求了什么地址.举个例子,在idea中,m ...