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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值