P2827 蚯蚓

暴力出奇迹!!!

昨晚很积极地拿手机看这道题的题面,还挺易懂的。

然后写了第二发程序,用优先队列再弄个delta轻轻松松85pts。。。

要是过几天考试能像这样该多好啊。。。



显然那个人挑出所有蚯蚓的最长的,就是堆的基本操作了。

然后想到没有挑出来的蚯蚓是会长长的,但是他们已经在堆里面,用优先队列不可能去修改他们啊!

其实直接维护个变量就可以了。

加新的蚯蚓就要记得减掉这个delta,把蚯蚓拿出来就记得加上这个delta,然后就没问题了。

所以轻松地拿到85pts。。。



为什么不能满分?因为这个\(m\)太大了。

看了题解才知道,这道题还有隐含的单调性:先被切的蚯蚓,长度肯定比后被切的蚯蚓长!

可以很感性地理解。

然后就可以用3个队列(算是单调队列),第一个装原蚯蚓,第二个装被切的短的蚯蚓,第三个装被切的长的蚯蚓。

每一次就从3个队头找出最大值,切掉他,分别扔进第二和第三个队列。

第二问也照着做就是了,没有什么思维难度。



几个小细节:

因为这个delta会越来越大,所以队列中的新蚯蚓的值会越来越小,所以最大值初始化要是负INF而不能是-1。

蚯蚓进第一个队列的时候记得从大到小排序啊!

代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#define ll long long
const int maxn = 100005;
const ll INF = 0x3f3f3f3f3f;
ll a[maxn];

std::queue<ll> qq[3];
ll delta = 0;
ll n, m, q, u, v, t;
double p;
bool cmp(ll a, ll b)
{
    return a > b;
}
ll read()
{
    ll ans = 0, s = 1;
    char ch = getchar();
    while(ch > ‘9‘ || ch < ‘0‘){ if(ch == ‘-‘) s = -1; ch = getchar(); }
    while(ch >= ‘0‘ && ch <= ‘9‘) ans = (ans << 3) + (ans << 1) + ch - ‘0‘, ch = getchar();
    return s * ans;
}
int main()
{
    n = read(), m = read(), q = read(), u = read(), v = read(), t = read();
    p = (double)(u) / (double)(v);
    for(int i = 1; i <= n; i++) a[i] = read();
    std::sort(a + 1, a + n + 1, cmp);
    for(int i = 1; i <= n; i++) qq[0].push(a[i]);
    bool first = true;
    for(int i = 1; i <= m; i++)
    {
        ll maxv = -INF, where = -1;
        for(int j = 0; j < 3; j++)
        {
            if(!qq[j].empty() && qq[j].front() > maxv) where = j, maxv = qq[j].front();
        }
        ll x = qq[where].front() + delta; qq[where].pop();
        if(i % t == 0)
        {
            if(first) printf("%lld", x), first = false;
            else printf(" %lld", x);
        }
        ll one = floor(p * x);
        ll other = x - one;
        if(one > other) std::swap(one, other);
        delta += q;
        qq[1].push(one - delta);
        qq[2].push(other - delta);
    }
    printf("\n");
    first = true;
    for(int i = 1; i <= n + m; i++)
    {
        ll maxv = -INF, where = -1;
        for(int j = 0; j < 3; j++)
        {
            if(!qq[j].empty() && qq[j].front() > maxv) where = j, maxv = qq[j].front();
        }
        ll x = qq[where].front() + delta; qq[where].pop();
        if(i % t == 0)
        {
            if(first) printf("%lld", x), first = false;
            else printf(" %lld", x);
        }
    }
    printf("\n");
    return 0;
}

原文地址:https://www.cnblogs.com/Garen-Wang/p/9813446.html

时间: 2024-11-02 02:07:40

P2827 蚯蚓的相关文章

做题记录:P2827 蚯蚓

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

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

【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 P2827 蚯蚓

看到题目就可以想到直接开的堆模拟的过程了吧,这个还是很naive的 注意在用堆做的时候也是要明智一点的,对于蚯蚓长度的相加肯定不能直接遍历并加上,还是可以差分一下的 其实说白了就是把集体加->单体减的一个小技巧,还是挺常用的. 然后看这个数据范围猜想应该是有什么\(O(n)\)的做法的,然后这就要发现题目中隐含的单调性 我们考虑讲所有的蚯蚓分个类,所有初始时没切割过的蚯蚓分为一类,每次切割产生的较长的蚯蚓分为一类,而产生的较短的蚯蚓分为一类 然后我们推到一下就可以发现,对于后面的两类蚯蚓,它们满

洛谷 P2827 BZOJ 4721 UOJ #264 蚯蚓

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

【noip2016】【洛谷P2827】蚯蚓

这个题只知道可以用优先队列去做,但是不知道正解想法,看到题解后恍然大悟,详情请看代码中间 #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; int n,m,q,u,v,t,q1[8000010],q2[8000010],q3[8000010],h1,h2,h3,t1,t2,t3

题解 P2827 【蚯蚓】

Solution 蚯蚓 题目大意:一开始有\(n\)只蚯蚓,你操作\(m\)次.每次抓最长的一只,记长度为\(x\),切成\(\lfloor px\rfloor\),\(x-\lfloor px\rfloor\)两只放回去,同时除这两只外的所有蚯蚓长度增加\(q\),问每次切断蚯蚓的长度,\(m\)次操作后所有蚯蚓的长度 队列 首先我们来解决除新增外集体增加\(q\)的问题,我们可以维护一个增量\(delta\),表示所有的蚯蚓的长度都要增加\(delta\),新增的两只蚯蚓不加\(q\),我们