Description
Luogu2827
有一些蚯蚓,每次取出最长的,切成两份,再放回去。求每次取出的蚯蚓长度和最后的所有蚯蚓长度。
Solution
首先可以想到应用堆来解决这个问题。然后,对于蚯蚓的生长,可以视作新蚯蚓的缩短,即两只新蚯蚓的长度各自减去(q*t),再取出时加上即可。
但是这样只能得80分。
通过看题解输出中间变量我们可以发现,其实这个题是有单调性的。
若蚯蚓(A)在(t_a)时刻被切开成(A_1,A_2),蚯蚓(B)在(t_b)时刻被切开成(B_1,B_2),且(l_A > l_B),易知(t_a < t_b),则(t)时刻,(l_{A_1} = pl_A+q(t-t_a)),(l_{B_1} = pl_B+q(t-t_b)),所以(l_{A_1} < l_{B_1}),同理(l_{A_2} < l_{B_2})。分成三个数组存储即可。
Code
#include <queue>
#include <algorithm>
#include <cstdio>
typedef long long ll;
const int N = 7e6 + 10;
const ll INF = 1e16;
struct Heap {
ll a[N];
ll sz;
ll p;
Heap() : p(1), sz(0) {}
void push(ll x) {
a[++sz] = x;
}
ll top() {
return p <= sz ? a[p] : -INF;
}
void pop() {
p++;
}
} heap[3];
int n, m, q, u, v, t;
bool cmp(const ll &a, const ll &b) {
return a > b;
}
int main() {
scanf("%d%d%d%d%d%d", &n, &m, &q, &u, &v, &t);
ll buf;
for (int i = 1; i <= n; ++i) {
scanf("%lld", &buf);
heap[0].push(buf);
}
std::sort(heap[0].a+1, heap[0].a+n+1, cmp);
ll a[3], mx = 0, mxp;
for (int i = 1; i <= m; ++i) {
mx = -INF; // mark
for (int j = 0; j < 3; ++j) {
a[j] = heap[j].top();
if (a[j] > mx) {
mx = a[j];
mxp = j;
}
}
heap[mxp].pop();
mx = (mx + (i-1)*q);
if (i % t == 0) printf("%lld ", mx);
heap[1].push(mx*u/v-i*q);
heap[2].push(mx-mx*u/v-i*q);
}
puts("");
int i = 0;
while (1) {
mx = -INF;
++i;
for (int j = 0; j < 3; ++j) {
a[j] = heap[j].top();
if (a[j] > mx) {
mx = a[j];
mxp = j;
}
}
if (mx == -INF) break;
mx = mx + q * m;
if (i % t == 0) printf("%lld ", mx);
heap[mxp].pop();
}
puts("");
return 0;
}
Note
mark
那里一开始写成了=0
。
有时候可以利用单调性优化很多最值问题
其实(l_{A_2} < l_{B_2})并不是很好证...