[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_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}\)并不是很好证...

posted @ 2018-09-10 20:14  wyxwyx  阅读(106)  评论(0编辑  收藏  举报