[NOIp2016]蚯蚓

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_B+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
有时候可以利用单调性优化很多最值问题

猜你喜欢

转载自www.cnblogs.com/wyxwyx/p/noip201622.html