You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
3.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// https://www.jisuanke.com/problem/T3690
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 3e5 + 10;
int a[N], b[N], c[N], n, k;
int T;
// ① 我喜欢的可以对于k变量每个贡献1的店铺
// ② 用一个大顶堆以访问需要的时长b[i]为权值保证这个堆的数量最多是k,那么堆顶的肯定花费时间更长的店,不划算的,准备放弃掉的店铺
priority_queue<int> q1;
// 被筛选下来的准备放弃掉的店铺放入到q2里
// 也是一个大顶堆
priority_queue<int> q2;
priority_queue<int, vector<int>, greater<int>> q3; // 小顶堆
LL res = -1; // 结果的默认值是-1
int sum1; // k个代价最小的店铺加在一起的总的访问花费时间。也就是q1中保留店铺的花费数字和
int sum2; // 被淘汰下来的店铺放在q2里q2中店铺的花费数字和
int main() {
freopen("street.in", "r", stdin);
freopen("street.out", "w", stdout);
cin >> n >> T >> k;
for (int i = 1; i <= n; i++) cin >> a[i]; // 从1号店到i号店需要的时间
for (int i = 1; i <= n; i++) cin >> b[i]; // 进入每个店内需要花费的时间
for (int i = 1; i <= n; i++) cin >> c[i]; // 每个店是不是喜欢的
for (int i = 1; i <= n; i++) { // 一次枚举每个店
if (c[i]) { // 如果当前店铺是我喜欢的
q1.push(b[i]); // q1里放入①我喜欢的②在优先队列中记录进入此店铺i中需要花费的时间
sum1 += b[i]; // sum1:记录进入所有k个以内店铺时需要的时间花费总和
if (q1.size() > k) { // 如果q1里面的个数已经达到k个那么就需要有某个店铺出队列
int x = q1.top(); // 因为是大顶堆,所以是堆顶元素出队列
q1.pop(); // 出队列
sum1 -= x; // 维护好sum1
q2.push(x); // 将q1中不是最优解的店移动到q2中去
sum2 += x; // 维护好q2中sum2的和
}
} else { // 如果当前店铺不是我喜欢的
q2.push(b[i]); // 直接放到q2里去
sum2 += b[i]; // 维护好q2中sum2的和
}
if (q1.size() < k) continue; // 如果还不够k个就继续考查下一个店铺
if (sum1 + a[i] > T) continue; // 如果当前的第i个店铺如果选择中就超出时间限制T,那没法选择i号店铺
int r = T - sum1 - a[i]; // 剩余的时间
// 不断交换q2中最大的 和 q3中最小的使得q2中都是代价小的q3中都是代价大的
while (q3.size() && q3.top() < q2.top()) {
int x = q2.top();
q2.pop();
q2.push(q3.top());
sum2 -= x;
sum2 += q3.top();
q3.pop();
q3.push(x);
}
// 剩余的时间不足以把q2中所有元素都访问到
while (q2.size() && r < sum2) {
int x = q2.top();
q3.push(x);
sum2 -= x;
q2.pop(); // 把q2中顶部最大的元素放到q3里去
}
while (q3.size() && r >= sum2 + q3.top()) {
int x = q3.top();
q2.push(x);
sum2 += x;
q3.pop();
}
// q.size()这个东东如果需要和int之类做加法必须加上强制转换
if (r >= sum2 && k + (int)q2.size() > res) res = k + (int)q2.size();
}
printf("%lld\n", res);
return 0;
}