CF854C planning 贪心题,维护堆; 送棵线段树

来源:互联网 发布:mysql编程题及答案 编辑:程序博客网 时间:2024/06/15 20:41

好像做过类似的题,给你一个数组每次从前k个元素中取出一个最大值(当然数组大小就减1),直到整个数组空。

就是维护一个大顶堆,每次从pop()弹出一个值。若还有数组队列还有元素,就push向堆中添加一个元素。直到堆空就可以了。

本题小心一下数据相乘时可能会爆int就OK了。

Planning

#include <iostream>#include <queue>using namespace std;const int N = 3e5 + 7;struct Flight {int c, id;Flight(int c = 0, int id = 0) :c(c), id(id) {}bool operator < (const Flight &tmp) const {return c < tmp.c;}}a[N];priority_queue<Flight> pq;int ans[N];int main(){ios::sync_with_stdio(false);int n, k;while (cin >> n >> k) {for (int i = 1; i <= n; ++i) {cin >> a[i].c;a[i].id = i;}int r = min(++k, n);for (int i = 1; i <= r; ++i) {pq.push(a[i]);}long long sum = 0;while (!pq.empty()) {Flight top = pq.top(); pq.pop();ans[top.id] = k;sum += (k - top.id) * (long long)top.c;if (++k <= n) {pq.push(a[k]);}}cout << sum << endl << ans[1];for (int i = 2; i <= n; ++i) {cout << " " << ans[i];}cout << endl;}return 0;}

只要能够在logn时间内找出前k项的最值,并且允许修改某一值,都可以过这道题。

送棵线段树,我室友是这样解的。线段树肯定比单调队列更耗时间和内存了。这棵线段树查询时返回[l = 1, r] 区间最值得索引id。然后用单点更新update(rt, id)将索引为id的数删掉(置小),当然删它不是目的,目的是更新维护线段树的性质。

#include <iostream>#include <algorithm>using namespace std;const int N = 3e5 + 7;int ans[N], a[N];struct Seg {int l, r, id, maxV;}t[N];void pushUp(int rt) {int tmp = rt << 1;if (t[rt << 1].maxV < t[rt << 1 | 1].maxV) tmp |= 1;t[rt].maxV = t[tmp].maxV;t[rt].id = t[tmp].id;}void build(int rt, int l, int r) {t[rt].l = l, t[rt].r = r;if (l == r) {t[rt].maxV = a[l];t[rt].id = l;return;}int mid = l + r >> 1;build(rt << 1, l, mid);build(rt << 1 | 1, mid + 1, r);pushUp(rt);}int query(int rt, int l, int r) {if (l <= t[rt].l && t[rt].r <= r) {return t[rt].id;}int mid = t[rt].l + t[rt].r >> 1;int id = 0, id2 = 0;if (l <= mid) id = query(rt << 1, l, r);if (r > mid) id2 = query(rt << 1 | 1, l, r);if (a[id2] > a[id]) id = id2;return id;}void update(int rt, int id) {if (t[rt].l == t[rt].r) {if (t[rt].l == id) {t[rt].maxV = a[t[rt].id] = -1;t[rt].id = 0;}return;}int mid = t[rt].l + t[rt].r >> 1;if (id <= mid) update(rt << 1, id);else update(rt << 1 | 1, id);pushUp(rt);}int main(){ios::sync_with_stdio(false);int n, k;while (cin >> n >> k) {a[0] = 0;for (int i = 1; i <= n; ++i) {cin >> a[i];}build(1, 1, n);long long sum = 0;for (int i = 1; i <= n; ++i) {int id = query(1, 1, min(++k, n));ans[id] = k;sum += (k - id) * (long long)a[id];update(1, id);}cout << sum << endl << ans[1];for (int i = 2; i <= n; ++i) {cout << " " << ans[i];}cout << endl;}return 0;}