分享贴里写的比较细的,扔题解区来
假设当前最大值为 $x$,那么会产生两只长为 $\left \lfloor px \right \rfloor$ 与 $x - \left \lfloor px \right \rfloor$ 的蚯蚓,然后所有的蚯蚓的长度加上 $q$。我们考虑曲线救国,即每次产生的蚯蚓长度都减去 $q$,然后记录一个偏移量 $delta$,使得每只蚯蚓的长度加上 $delta$ 就是真实数值。
具体的,起初,我们令 $delta = 0$,每次:
- 找到长度最长的一只蚯蚓,长度为 $x$,令 $x = x + delta$
- 插入 $\lfloor px \rfloor - delta - q$ 和 $x - \lfloor px \rfloor - delta - q$ 两只蚯蚓
- 令 $delta = delta + q$
由于每次需要 $O(n)$ 的时间寻找最大值,所以总时间复杂度是 $O(N^2)$ 的,不足以通过。
我们考虑如何快速求出集合的最大值。我们大胆猜想蚯蚓长度一定满足某种性质,可以证明对于两只长度为 $x_1$ 和 $x_2 + q$ 的蚯蚓,一定存在 $\lfloor px_1 \rfloor + q \geq \lfloor p(x_2 + q) \rfloor$ 且 $x_1 - \lfloor px_1 \rfloor + q \geq x_2 + q - \lfloor p(x_2 + q) \rfloor$。即若 $x_1$ 比 $x_2$ 先取出,那$x_1$ 分成的两只蚯蚓一定分别大于等于 $x_2 + q$ 分成的两只蚯蚓。
证明:
先证明 $x_1 - \lfloor px_1 \rfloor \geq x_2 - \lfloor px_2 \rfloor$
由于 $x_1 - x_2 \geq p(x_1 - x_2)$
所以 $\lfloor x_1 - x_2 + px_2 \rfloor \geq \lfloor px_1 \rfloor$
所以 $x_1 - x_2 + \lfloor px_2 \rfloor \geq \lfloor px_1 \rfloor$
从而 $x_1 - \lfloor px_1 \rfloor \geq x_2 - \lfloor px_1 \rfloor$
得证。
然后由于 $x_1 \geq x_2, 0 < p < q$ ,
所以 $px_1 + q \geq px_2 + pq$ 且 $px_2 \leq p(x_2 + q)$
从而 $\lfloor px_1 \rfloor + q = \lfloor px_1 + q \rfloor \geq \lfloor px_2 + pq \rfloor = \lfloor p(x_2 + q) \rfloor$ 且 $ x_1 - \lfloor px_1 \rfloor + q \geq x_2 - \lfloor px_2 \rfloor + q \geq x_2 + q - \lfloor p(x_2 + q) \rfloor$
证毕。
所以不仅我们取出的数是单调递减的,新产生的两类数值也是单调递减的。
我们可以建立三个队列 $A,B,C$,其中 $A$ 存原序列从大到小排序的结果,$B$ 存 $\lfloor px \rfloor$ 的情况,$C$ 存 $x - \lfloor px \rfloor$ 的情况。由于以上性质,最大值只可能是 $A,B,C$ 分别的队头,取出最大值然后删除对应蚯蚓,加入新的蚯蚓即可。
如果用 queue
的话可能会卡常,需要吸氧。
#pragma GCC optimize(2)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 100010, INF = 0x3f3f3f3f;
int n, m, q, u, v, t;
int a[N];
queue<int> que[4];
int main() {
scanf("%d%d%d%d%d%d", &n, &m, &q, &u, &v, &t);
for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
sort(a + 1, a + 1 + n, [&](int a, int b) {
return a > b;
});
for (int i = 1; i <= n; i ++) que[1].push(a[i]);
for (int i = 0; i < m; i ++) {
PII maxx = max({make_pair(que[1].empty() ? -INF : que[1].front(), 1),
make_pair(que[2].empty() ? -INF : que[2].front(), 2),
make_pair(que[3].empty() ? -INF : que[3].front(), 3)});
int val = maxx.first + i * q, id = maxx.second;
que[id].pop();
int x = 1ll * val * u / v, y = val - x;
que[2].push(x - q * (i + 1)); que[3].push(y - q * (i + 1));
if (i % t == t - 1)
printf("%d ", val);
}
puts("");
for (int i = 1; i <= n + m; i ++) {
PII maxx = max({make_pair(que[1].empty() ? -INF : que[1].front(), 1),
make_pair(que[2].empty() ? -INF : que[2].front(), 2),
make_pair(que[3].empty() ? -INF : que[3].front(), 3)});
que[maxx.second].pop();
if (i % t == 0)
printf("%d ", maxx.first + q * m);
}
return 0;
}