题面:

传送门:https://www.luogu.org/problemnew/show/P2827


Solution

看到这题,我们肯定会有一个大胆想法。

那就是直接用堆模拟这个过程。

对于q,我们只需要在堆中多维护一个T,记录每个点插入的时间,在新的元素插入时直接计算所比较的点的当前长度就可以完成插入了。

时间复杂度O(M*log(M))

这样的做法只能获得65-70分,因为后面的数据非常大。

所以说,我们要另寻他路。

首先,我们经过看题解手玩可以发现一个很显然但是很重要的结论:

在q=0的时候,一条线段所分裂出来的两条线段肯定要比它更小的线段分裂出来的对应的两条线段更大。

证明十分简单,设x,y为两条分裂前的线段,且x>y

那么,较长的那一条(假设p>0.5(p为分割点)) 为: px 与 py, 显然,px>py

同理可证另一条线段也有这种关系。

根据这个关系,我们可以考虑这样的做法:

我们开三个队列,第一个队列放入排好序的原序列,第二个队列放每次分裂出来的较长的蚯蚓,第三个放每次分裂出来的较短的蚯蚓

那么根据刚才的证明,我们可以得出,第二个与第三个队列一定是有序的,因为我们每次取的蚯蚓一定比之前取的更短,所以分裂出来的肯定比比之前分裂出来的蚯蚓更短

这样子,我们就可以模拟这个过程,每次取三个队列中最大的那一个,并把分裂出来的对应放到第二第三个队列的末尾就好。

事实上,对于q>0的情况,这个推论也是成立的。

首先,我们可以假设出来x与y分别是分裂前的线段长度且x>y,假设x与y之间间隔的时间为T

那么,在y分裂的时刻,x分裂出来的线段较长的长度为(假设p>0.5):px+T*q ; y分裂出来的较长的线段长度为: (y+T*q)*p = py + T*q*p

显然  px+T*q > py + T*q*p

所以说,我们刚刚的结论在这里也是成立的。

对于在某一时刻的线段的具体长度,我们可以通过在队列中多记录一个插入时间,这样就可以算出某一时刻的某条线段的具体长度了。

时间复杂度O(nlogn+m)

就酱,我们就可以AC这道题啦(≧ω≦)/


Code

//Luogu P2827 蚯蚓
//Sep,9th,2018
//巧妙的三个队列
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
long long read()
{
long long x=0,f=1; char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int N=100000+100;
const int M=7000000+N+2000;
int a[M],n,m,q,u,v,t;
struct worm
{
int T,s;
worm (int A,int B)
{
s=A,T=B;
}
inline int GetLen(int mtime)//mtime秒后的长度
{
return s+(mtime-T)*q;
}
};
queue <worm> A,B,C;
double p;
bool cmp(int x,int y)
{
return x>y;
}
int main()
{
n=read(),m=read(),q=read(),u=read(),v=read(),t=read();
for(int i=1;i<=n;i++)
a[i]=read(); sort(a+1,a+1+n);
for(int i=n;i>=1;i--)
A.push(worm(a[i],0));
for(int i=1;i<=m;i++)
{
long long from=-1,t_MAX=-0x3f3f3f3f;
if(A.empty()==false) from=1,t_MAX=A.front().GetLen(i-1);
if(B.empty()==false and B.front().GetLen(i-1)>t_MAX) from=2,t_MAX=B.front().GetLen(i-1);
if(C.empty()==false and C.front().GetLen(i-1)>t_MAX) from=3,t_MAX=C.front().GetLen(i-1);
int px=(t_MAX*u)/v,t_px=t_MAX-px;
B.push(worm(max(px,t_px),i));
C.push(worm(min(px,t_px),i));
if(from==1) A.pop();
else if(from==2) B.pop();
else C.pop();
if(i%t==0)
printf("%lld ",t_MAX);
}
printf("\n"); n=0;
while(A.empty()==false)
a[++n]=A.front().GetLen(m),A.pop();
while(B.empty()==false)
a[++n]=B.front().GetLen(m),B.pop();
while(C.empty()==false)
a[++n]=C.front().GetLen(m),C.pop();
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
if(i%t==0)
printf("%d ",a[i]);
return 0;
}

[Luogu P2827] 蚯蚓 (巧妙的模拟)的更多相关文章

  1. Luogu P2827 蚯蚓(模拟)

    P2827 蚯蚓 题意 题目描述 本题中,我们将用符号\(\lfloor c\rfloor\)表示对\(c\)向下取整,例如:\(\lfloor 3.0\rfloor =\lfloor 3.1\rfl ...

  2. Luogu P2827 蚯蚓

    看到题目就可以想到直接开的堆模拟的过程了吧,这个还是很naive的 注意在用堆做的时候也是要明智一点的,对于蚯蚓长度的相加肯定不能直接遍历并加上,还是可以差分一下的 其实说白了就是把集体加->单 ...

  3. 【luogu P2827 蚯蚓】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2827 35分:暴力sortO(mnlogn). 80分:考虑到每次不好维护不被切的点+q,正难则反.改成维护 ...

  4. LUOGU P2827 蚯蚓 (noip 2016)

    传送门 解题思路 第一眼以为是一个二叉堆,直接上优先队列60分...后来听ztz11说有单调性,新加入的蚯蚓一定比原先在的蚯蚓长度长,开三个队列,分别放原先的长度,切掉后大的那一半,切掉后小的那一半. ...

  5. 洛谷P2827 蚯蚓——思路题

    题目:https://www.luogu.org/problemnew/show/P2827 思路... 用优先队列模拟做的话,时间主要消耗在每次的排序上: 能不能不要每次排序呢? 关注先后被砍的两条 ...

  6. 洛谷——P2827 蚯蚓

    P2827 蚯蚓 题目描述 本题中,我们将用符号 \lfloor c \rfloor⌊c⌋ 表示对 cc 向下取整,例如:\lfloor 3.0 \rfloor = \lfloor 3.1 \rflo ...

  7. 【巧妙的模拟】【UVA 10881】 - Piotr's Ants/Piotr的蚂蚁

    </pre></center><center style="font-family: Simsun;font-size:14px;"><s ...

  8. 洛谷P2827 蚯蚓 题解

    洛谷P2827 蚯蚓 题解 题目描述 本题中,我们将用符号 ⌊c⌋ 表示对 c 向下取整. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现 ...

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

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

随机推荐

  1. getchar()与putchar()

    getchar() 用于读取用户从键盘输入的单个字符,它有一个整型的返回值,当发生读取错误的时候,返回整型值-1,当读取正确的时候,它会返回用户从键盘输的第一个字符的ASCII码, 当程序调用getc ...

  2. spark-3-macOS配置hadoop+spark+IDE

    [教程1]https://blog.csdn.net/shiyutianming/article/details/99946797  + [教程2]http://dblab.xmu.edu.cn/bl ...

  3. 007 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 01 Java标识符

    007 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 01 Java标识符 Java变量与常量主要内容 Java变量与常量主要内容如下,主要是对以下内容的学习,没 ...

  4. Java知识系统回顾整理01基础06数组05复制数组

    数组的长度是不可变的,一旦分配好空间,是多长,就多长,不能增加也不能减少 一.复制数组 把一个数组的值,复制到另一个数组中 System.arraycopy(src, srcPos, dest, de ...

  5. python数据结构之二叉树的遍历实例

    遍历方案   从二叉树的递归定义可知,一棵非空的二叉树由根结点及左.右子树这三个基本部分组成.因此,在任一给定结点上,可以按某种次序执行三个操作:   1).访问结点本身(N)   2).遍历该结点的 ...

  6. Java中的对象都是在堆上分配的吗?

    作者:LittleMagic https://www.jianshu.com/p/8377e09971b8 为了防止歧义,可以换个说法: Java对象实例和数组元素都是在堆上分配内存的吗? 答:不一定 ...

  7. 解决vue、js 下载图片浏览器默认预览而不是下载

    在网页上,如果我们下载的地址对应的是一个jpg文件,txt文件等,点击链接时,浏览器默认的是打开这些文件而不是下载,那么如何才能实现默认下载呢? 后端解决 这就是Content-Disposition ...

  8. C++调用全局函数与类成员函数

    void testfunc(void *param) { printf("\n\tcall global function %s\n", param); } void *GetCl ...

  9. 多测师全方位面试题腾讯 _自动化面试题_高级讲师肖sir

    作答注意:候选人可以两题都做,也可以两题任选一题做即可. 笔试题一:1.查询 https://www.newsmth.net/nForum/#!board/PieLove2.获取发贴时间是2020年8 ...

  10. 发布MeteoInfo 2.3

    主要的更新如下: Using SVG icons in GUI. Update netCDF java library to 5.3.3. Update FlatLaf to 0.40. Update ...