P2827题解

题面:

蚯蚓

分析:

注意到 \(p,q\) 是固定常熟,\(0<p<1\)\(q\) 是非负整数。

\(x_1,x_2\) 为非负整数且 \(x_1\ge x_2\)
\(\therefore\left\lfloor px_1\right\rfloor+q=\left\lfloor px_1+q\right\rfloor\ge \left\lfloor px_2+pq\right\rfloor=\left\lfloor p(x_2+q)\right\rfloor\\\because x_1-x_2>p(x_1-x_2)\\\therefore x_1-px_1>x_2-px_2\ge x_2-p(x_2+q)\\\therefore x_1-\left\lfloor px_1\right\rfloor +q=\left\lfloor x_1-px_1\right\rfloor +q\ge \left\lfloor x_2-p(x_2+q)\right\rfloor+q=x_2+q-\left\lfloor p(x_2+q)\right\rfloor\)

根据上面推出来的结论,我们可以发现,若 \(x_1\)\(x_2\) 之前取出,则一秒后由 \(x_1\) 产生的两个数 \(\left\lfloor px_1\right\rfloor+q\)\(x_1-\left\lfloor px_1\right\rfloor+q\) 分别大于等于由 \(x_2+q\) 产生的两个数 \(\left\lfloor p(x_2+q)\right\rfloor\)\(x_2+q-\left\lfloor p(x_2+q)\right\rfloor\)
因此,若从集合中取出的数是单调递减的,则新产生的数也随着时间单调递减。

因此,我们可以建立三个队列 \(A,B,C\)(其中队列 \(A\) 为大根堆)。队列 \(A\) 存原序列,队列 \(B\) 存产生的第一个数值,队列 \(C\) 存产生的第二个数值。显然,三个队列都是单调递减的,因此每个时刻的最大值是三个队列的队首之一。

在这个结论的基础上,我们维护一个偏移量 \(delta\),使集合中的每一个数加上 \(delta\) 便是它的真实数值。在计算时将集合中的数加上 \(delta\) 即可。

Code:

/*
user:xcj
time:2022.4.8
*/
#include <bits/stdc++.h>
#define int long long
using namespace std;

priority_queue < int > q;
queue < int > q1, q2;

int n, m, k, u, v, t, delta;

inline int read(){
    int s = 0, w = 1;
    char ch = getchar();
    for (; ch < '0' || ch > '9'; w *= ch == '-' ? -1 : 1, ch = getchar());
    for (; ch >= '0' && ch <= '9'; s = s * 10 + ch - '0', ch = getchar());
    return s * w;
}

signed main(){
    n = read(), m = read(), k = read(), u = read(), v = read(), t = read();
    for (int i = 1, x; i <= n; ++i) x = read(), q.push(x);
    for (int i = 1, f, maxn; i <= m; ++i){
        maxn = -2147482597;
        if (q.size() && q.top() > maxn) maxn = q.top(), f = 0;
        if (q1.size() && q1.front() > maxn) maxn = q1.front(), f = 1;
        if (q2.size() && q2.front() > maxn) maxn = q2.front(), f = 2;
        if (!f) q.pop();
        else if (f < 2) q1.pop();
        else q2.pop();
        maxn += delta;
        q1.push(maxn * u / v - delta - k), q2.push(maxn - maxn * u / v - delta - k);
        delta += k;
        if (i % t == 0) printf("%lld ", maxn);
    }
    puts("");
    for (int i = 1, maxn, f; i <= n + m; ++i){
        maxn = -2147482597;
        if (q.size() && q.top() > maxn) maxn = q.top(), f = 0;
        if (q1.size() && q1.front() > maxn) maxn = q1.front(), f = 1;
        if (q2.size() && q2.front() > maxn) maxn = q2.front(), f = 2;
        if (!f) q.pop();
        else if (f < 2) q1.pop();
        else q2.pop();
        if (i % t == 0) printf("%lld ", maxn + delta);
    }
    puts("");
    return 0;
}
posted @ 2022-04-08 18:39  leoair  阅读(32)  评论(0)    收藏  举报