好像做过类似的题,给你一个数组每次从前k个元素中取出一个最大值(当然数组大小就减1),直到整个数组空。
就是维护一个大顶堆,每次从pop()弹出一个值。若还有数组队列还有元素,就push向堆中添加一个元素。直到堆空就可以了。
本题小心一下数据相乘时可能会爆int就OK了。
#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;
}
\
\