Kevin逛超市 2 (困难版本)
Kevin逛超市 2 (困难版本)
堆反悔贪心
#include <bits/stdc++.h>
using namespace std;
void solve() {
int n, a, b;
long long x, y;
cin >> n >> a >> b >> x >> y;
vector<long double> p(n);
long double total = 0;
for(int i = 0; i < n; i ++) {
cin >> p[i];
total += p[i];
}
sort(p.begin(), p.end(), greater<long double>());
long double alpha = (100.0L - x) / 100.0L; // 折扣比例
vector<int> state(n, 0); // state: 0 未使用, 1 使用折扣券, 2 使用立减券
priority_queue<pair<long double, int>> pq;
long double save = 0;
// 初始:价格最高的 a 个商品使用折扣券
int u = a; // 指向第一个未使用商品
for(int i = 0; i < a; i ++) {
state[i] = 1;
save += alpha * p[i];
long double r = min(p[i], (long double)y) - alpha * p[i];
pq.push({r, i});
}
for(int used = 0; used < b; used ++) {
// 清除堆中已经无效的元素
while(!pq.empty() && state[pq.top().second] != 1) pq.pop();
bool hasDiscount = !pq.empty();
bool hasUnused = (u < n);
long double incA = -1e100L; // 直接立减未使用最高价
long double incB = -1e100L; // 替换一张折扣券,并把折扣券给未使用最高价
if(hasUnused) incA = min(p[u], (long double)y);
if(hasDiscount) {
long double maxR = pq.top().first;
if(hasUnused) incB = maxR + alpha * p[u];
else incB = maxR;
}
long double inc = max(incA, incB);
if(inc <= 0) break;
if(incA >= incB) {
// 直接给未使用最高价商品使用立减券
save += incA;
state[u] = 2;
u ++;
}
else {
// 替换一张折扣券
auto [rval, id] = pq.top(); pq.pop();
save += incB;
state[id] = 2;
if(hasUnused) {// 空出的折扣券给未使用最高价商品
state[u] = 1;
long double newR = min(p[u], (long double)y) - alpha * p[u];
pq.push({newR, u});
u ++;
}
}
}
long double ans = total - save;
cout << fixed << setprecision(12) << (double)ans << '\n';
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
int _; cin >> _;
while(_--) solve();
return 0;
}

浙公网安备 33010602011771号