Luogu P2827 蚯蚓

看到题目就可以想到直接开的堆模拟的过程了吧,这个还是很naive的

注意在用堆做的时候也是要明智一点的,对于蚯蚓长度的相加肯定不能直接遍历并加上,还是可以差分一下的

其实说白了就是把集体加->单体减的一个小技巧,还是挺常用的。

然后看这个数据范围猜想应该是有什么\(O(n)\)的做法的,然后这就要发现题目中隐含的单调性

我们考虑讲所有的蚯蚓分个类,所有初始时没切割过的蚯蚓分为一类,每次切割产生的较长的蚯蚓分为一类,而产生的较短的蚯蚓分为一类

然后我们推到一下就可以发现,对于后面的两类蚯蚓,它们满足单调性

因为我们根据切割的过程可以发现:

  • 先切割的蚯蚓长度一定比后切割的蚯蚓长度长
  • 同一种切法,后切割的一定比先切割的短

所以我们再对初始的蚯蚓长度拍个序,就可以得到三个单调的队列(注意不是单调队列),每一次比较时我们取出队首并切割最长的一只再丢进第二队,第三队即可

差分的思想还是要的,不过这里直接记录了每一只蚯蚓进队的时间,每次注意加上增长的长度

细节比较多,最后对这三队蚯蚓做一次归并即可(因为都是有序的)

因此复杂度为\(O(n\ logn+m)\)

CODE

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
const int N=100005,M=7000005;
int n,m,q,u,v,t,a[N],que[3][M],num[3][M],H[3],T[3],cut[M],ans[N+M],temp[N+M],cnt,tot;
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
    x=0; char ch; while (!isdigit(ch=tc()));
    while (x=(x<<3)+(x<<1)+ch-‘0‘,isdigit(ch=tc()));
}
inline void write(int x)
{
    if (x>9) write(x/10);
    putchar(x%10+‘0‘);
}
inline bool cmp(int x,int y)
{
    return x>y;
}
inline void swap(int &a,int &b)
{
    int t=a; a=b; b=t;
}
inline void merge(void)
{
    register int i=H[0],j=H[1];
    while (i<=T[0]&&j<=T[1])
    if (que[0][i]+(m-num[0][i])*q>que[1][j]+(m-num[1][j])*q) temp[++cnt]=que[0][i]+(m-num[0][i])*q,++i;
    else temp[++cnt]=que[1][j]+(m-num[1][j])*q,++j;
    for (;i<=T[0];++i) temp[++cnt]=que[0][i]+(m-num[0][i])*q;
    for (;j<=T[1];++j) temp[++cnt]=que[1][j]+(m-num[1][j])*q;
    i=1; j=H[2];
    while (i<=cnt&&j<=T[2])
    if (temp[i]>que[2][j]+(m-num[2][j])*q) ans[++tot]=temp[i],++i; else ans[++tot]=que[2][j]+(m-num[2][j])*q,++j;
    for (;i<=cnt;++i) ans[++tot]=temp[i];
    for (;j<=T[2];++j) ans[++tot]=que[2][j]+(m-num[2][j])*q;
}
inline void print(void)
{
    for (register int i=t;i<=m;i+=t)
    write(cut[i]),putchar(‘ ‘); putchar(‘\n‘);
    for (register int i=t;i<=n+m;i+=t)
    write(ans[i]),putchar(‘ ‘);
}
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    register int i,j; read(n); read(m); read(q); read(u); read(v); read(t);
    for (i=1;i<=n;++i) read(a[i]); sort(a+1,a+n+1,cmp);
    for (i=1;i<=n;++i) que[0][++T[0]]=a[i]; H[0]=H[1]=H[2]=1;
    for (i=1;i<=m;++i)
    {
        int len=-1,id;
        for (j=0;j<3;++j)
        if (H[j]<=T[j]) if (que[j][H[j]]+(i-num[j][H[j]]-1)*q>len) len=que[j][H[j]]+(i-num[j][H[j]]-1)*q,id=j;
        cut[i]=len; ++H[id]; int x=1LL*len*u/v,y=len-x; if (x<y) swap(x,y);
        que[1][++T[1]]=x; num[1][T[1]]=i; que[2][++T[2]]=y; num[2][T[2]]=i;
    }
    merge(); print(); return 0;
}

原文地址:https://www.cnblogs.com/cjjsb/p/9439810.html

时间: 2024-11-09 09:49:48

Luogu P2827 蚯蚓的相关文章

Luogu P2827 蚯蚓(模拟)

P2827 蚯蚓 题意 题目描述 本题中,我们将用符号\(\lfloor c\rfloor\)表示对\(c\)向下取整,例如:\(\lfloor 3.0\rfloor =\lfloor 3.1\rfloor =\lfloor 3.9\rfloor =3\). 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有\(n\)只蚯蚓(\(n\)为正整数).每只蚯蚓拥有长度,我们设第\(i\)只蚯蚓的长度为\(a_i(i=1,2,\dots

做题记录:P2827 蚯蚓

P2827 蚯蚓 AC代码: /* 思路:三队列模拟. 第一个队列存放原始的蚯蚓长度(已从大到小排序). 第二个队列存放蚯蚓被切后的一份的长度([px]). 第三个队列存放蚯蚓被切后的另一份的长度(x-[px]). 每次在三个队列的队头中取一个最大值并将其出队,然后将其分成两份分别存在第二.三个队列里. 因为每一次我们都是切最长的,而当我们切下一条时两条原来属于上一条的蚯蚓又会增长, 所以先切一定大于后切的,第二.三个队列也就是单调递减的了. 除此之外,还要加一个标记,记录当前每一条蚯蚓应增加的

【Luogu】P2827蚯蚓(堆转队列)

按照国际惯例先发题目链接? woc从4月就开始做这sb题.最开始30分升到65分不管了,直到最近几天升到85分,再到今天AC.激动的心情自然是那些一遍就A或者一小时以内就A的神犇难以想象的. 下面说说主要几个分段. # 35分 按题意用堆模拟.每次暴力修改蚯蚓长度,于是get皮肤:TLE蓝. # 65分 考虑到暴力修改消耗的时间复杂度过大,于是考虑偷懒.既然我们不能暴力增长已经存进堆的蚯蚓长度,那就剪短将要存进堆的蚯蚓长度.将目前蚯蚓增加的长度记为mark,从堆里取出来的蚯蚓长度+mark,要存

洛谷 P2827 蚯蚓(NOIp2016提高组D2T2)

题目描述 本题中,我们将用符号?c?表示对c向下取整,例如:?3.0?=?3.1?=?3.9?=3. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只蚯蚓拥有长度,我们设第i只蚯蚓的长度为a_i(i=1,2,...,n)a?i??(i=1,2,...,n),并保证所有的长度都是非负整数(即:可能存在长度为0的蚯蚓). 每一秒,神刀手会在所有的蚯蚓中,准确地找到最长的那一只(如有多个则任选一个)将其切成两

洛谷 P2827 蚯蚓

题目描述 本题中,我们将用符号\lfloor c \rfloor⌊c⌋表示对c向下取整,例如:\lfloor 3.0 \rfloor= \lfloor 3.1 \rfloor=\lfloor 3.9 \rfloor=3⌊3.0⌋=⌊3.1⌋=⌊3.9⌋=3. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只蚯蚓拥有长度,我们设第i只蚯蚓的长度为a_i(i=1,2,...,n)a?i??(i=1,2,..

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

易知可利用优先队列选取最大值: 但是通过分析可知,先取出的蚯蚓分开后仍然要比后分的长,所以可直接利用单调队列找队头即可,分三个单调队列,分别找未切割,切割,切割2三种情况 #include<bits/stdc++.h> #define rep(i,x,y) for(register int i=x;i<=y;i++) #define ll long long using namespace std; const int inf=2147483647; const int N=1e5+5;

P2827 蚯蚓

暴力出奇迹!!! 昨晚很积极地拿手机看这道题的题面,还挺易懂的. 然后写了第二发程序,用优先队列再弄个delta轻轻松松85pts... 要是过几天考试能像这样该多好啊... 显然那个人挑出所有蚯蚓的最长的,就是堆的基本操作了. 然后想到没有挑出来的蚯蚓是会长长的,但是他们已经在堆里面,用优先队列不可能去修改他们啊! 其实直接维护个变量就可以了. 加新的蚯蚓就要记得减掉这个delta,把蚯蚓拿出来就记得加上这个delta,然后就没问题了. 所以轻松地拿到85pts... 为什么不能满分?因为这个

浴谷夏令营题单

这是群里一位神犇整理的,我只负责将它们做完. 一.暴力.搜索Luogu 1588 丢失的牛Luogu 1463 [SDOI2005]反素数antBzoj 1085 [SCOI2005]骑士精神Luogu 1019 单词接龙Luogu 1078 文化之旅Luogu 1312 Mayan游戏Luogu 3823 蚯蚓排队Codeforces 444B Codeforces 555DLuogu 1979 华容道 二.初等数论Poj 3292 H合成数Luogu 1890 gcd区间Luogu 1029

NOIP 2016 蚯蚓 (luogu 2827 &amp; uoj 264) - 鬼畜的优化

题目描述 本题中,我们将用符号\lfloor c \rfloor⌊c⌋表示对c向下取整,例如:\lfloor 3.0 \rfloor= \lfloor 3.1 \rfloor=\lfloor 3.9 \rfloor=3⌊3.0⌋=⌊3.1⌋=⌊3.9⌋=3. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只蚯蚓拥有长度,我们设第i只蚯蚓的长度为a_i(i=1,2,...,n)ai?(i=1,2,...,