反悔贪心
用处
这个不知道怎么说。
如果能够抵消之前操作的贪心,都叫反悔贪心吧。
直接看例题。
题目
CF865D Buy Low Sell High
最经典的反悔贪。
如果买入了一个价值为 \(a_i\) 的股票,可以在价值为 \(a_j\) 的时候卖出,当然,可能在价值为 \(a_k\) 卖出的时候价值更高,那怎么办?
举个例子。
对于股票序列:1 2 100。
先考虑维护一个集合,表示可以买入的股票价值。
最开始把价值为 \(1\) 的股票放进集合中,表示可以买这个股票。
当股票价值为 \(2\) 时,发现如果此时卖出,可以获得 \(1\) 的价值,那么卖出此股票,但是为了反悔,再在集合中加入价值为 \(2\) 的股票。
当股票价值为 \(100\) 时,集合中还有一个价值为 \(2\) 的股票,那么可以买入这个价值为 \(2\) 的股票,获得 \(98\) 的价值。
最终获得了 \(99\) 的价值,也就等于在价值为 \(1\) 时买入股票,在价值为 \(100\) 时卖出股票,对于在价值为 \(2\) 时卖出股票的操作被反悔掉了。
现在总结一下这道题的流程:
- 按顺序枚举股票。
- 对于当前价值为 \(a_i\) 的股票,如果要卖出它:
- 考虑在集合中找到一个价值最小的股票,设为 \(x\)。
- 如果 \(a_i\gt x\),也就是卖出能够赚钱,那么就卖出价值 \(a_i\) 的股票,同时往集合中加入价值为 \(a_i\) 的股票,如果在后面选择这价值 \(a_i\) 的股票,就表示把卖出它的操作给反悔掉了。
- 如果不选择卖出价值为 \(a_i\) 的股票,那么把它加入集合。
代码
#include <bits/stdc++.h>
#define int long long
void Freopen() {
freopen("", "r", stdin);
freopen("", "w", stdout);
}
using namespace std;
const int N = 3e5 + 10, M = 2e5 + 10, inf = 1e9, mod = 998244353;
int n, ans;
int a[N];
priority_queue< int> q;
signed main() {
ios :: sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for ( int i = 1; i <= n; i ++) cin >> a[i];
for ( int i = 1; i <= n; i ++) {
if (q.size()) {
int x = -q.top();
if (a[i] > x) ans += a[i] - x, q.pop(), q.push(-a[i]);
}
// 这里表示要卖出 a_i
q.push(-a[i]);
// 这里表示不卖出 a_i
}
cout << ans << '\n';
return 0;
}
[JSOI2007] 建筑抢修
首先先按照 \(T_2\) 从小到大排序。
然后遍历嘛,记录一个遍历 now 表示当前用的时间,同时维护一个集合,存修过的房子的 \(T_1\)。
现在遍历到房子 \(i\),如果时间够修房子 \(i\),那么直接修了;如果不行,则在集合中选出最大的 \(T_1\),记对应的房子编号为 \(j\),如果 \({T_1}_j\gt {T_1}_i\),那么就进行反悔:反悔修房子 \(j\),而修房子 \(i\)。
为什么这样做最优?因为无论如何都只能在房子 \(i\)、\(j\) 中选一个修了,但是修房子 \(i\) 占用的时间更小,能够给后面的房子留下更多时间,所以选择房子 \(i\)。
代码
#include <bits/stdc++.h>
#define int long long
void Freopen() {
freopen("", "r", stdin);
freopen("", "w", stdout);
}
using namespace std;
const int N = 2e5 + 10, M = 2e5 + 10, inf = 1e9, mod = 998244353;
int n;
struct node {
int t1, t2;
} p[N];
priority_queue< int> q;
signed main() {
ios :: sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for ( int i = 1; i <= n; i ++) {
cin >> p[i].t1 >> p[i].t2;
}
sort(p + 1, p + n + 1, [&]( node a, node b) {
return a.t2 == b.t2 ? a.t1 < b.t1 : a.t2 < b.t2;
});
int ans = 0, now = 0;
for ( int i = 1; i <= n; i ++) {
if (now + p[i].t1 <= p[i].t2) now += p[i].t1, ans ++, q.push(p[i].t1);
else {
if (q.size()) {
int x = q.top();
if (x > p[i].t1) now = now - x + p[i].t1, q.pop(), q.push(p[i].t1);
}
}
}
cout << ans << '\n';
return 0;
}

浙公网安备 33010602011771号