可撤销贪心
Posted uid001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可撤销贪心相关的知识,希望对你有一定的参考价值。
1. CF 867E Buy Low Sell High
大意: 第$i$天可以花$a_i$元买入或卖出一股或者什么也不干, 初始没钱, 求$n$天后最大收益.
用堆维护最小值, 假设当前考虑的值为$a_i$, 堆中最小值为$t$, 则卖出贡献$a_i-t$, 若贡献$>0$直接加上, 然后再填进去一个$a_i$, 之后若有更优值$x$, 总贡献会变为$x-a_i+a_i-t$, 也就相当于进行反悔操作.
#include <iostream> #include <cstdio> #include <queue> using namespace std; typedef long long ll; int main() { int n; scanf("%d", &n); priority_queue<int,vector<int>,greater<int> > q; ll ans = 0; while (n--) { int t; scanf("%d", &t); q.push(t); if (t>q.top()) { ans += t-q.top(); q.pop(); q.push(t); } } printf("%lld\n", ans); }
2. luogu P1484 种树
cyrcyr今天在种树,他在一条直线上挖了n个坑。这n个坑都可以种树,但为了保证每一棵树都有充足的养料,cyrcyr不会在相邻的两个坑中种树。而且由于cyrcyr的树种不够,他至多会种k棵树。假设cyrcyr有某种神能力,能预知自己在某个坑种树的获利会是多少(可能为负),请你帮助他计算出他的最大获利。
#include <iostream> #include <algorithm> #include <string.h> #include <queue> #define REP(i,a,n) for(int i=a;i<=n;++i) using namespace std; typedef long long ll; const int N = 500010; bool vis[N]; struct node { int u, d; bool operator < (const node& rhs) const { return d<rhs.d; } }a[N]; int l[N], r[N]; ll w[N]; priority_queue<node> q; int main() { int n, k; scanf("%d%d", &n, &k); REP(i,1,n) { node x{i}; scanf("%d", &x.d); q.push(x); l[i] = i-1, r[i] = i+1, w[i]=x.d; } ll ans = 0; REP(i,1,k) { while (vis[q.top().u]) q.pop(); node t = q.top(); q.pop(); if (t.d<0) break; ans += t.d; w[t.u] = t.d = w[l[t.u]]+w[r[t.u]]-w[t.u]; vis[l[t.u]] = vis[r[t.u]] = 1; l[t.u] = l[l[t.u]]; r[l[t.u]] = t.u; r[t.u] = r[r[t.u]]; l[r[t.u]] = t.u; q.push(t); } printf("%lld\n", ans); }
3. ZOJ 4043
第一行给n个数,第二行给m个数,m<=n,从n个数中取m个数和第二行的m个数匹配,匹配花费abs(ai-bj),求最小匹配花费
#include<cstdio> #include<queue> #include<vector> #include<algorithm> using namespace std; typedef long long ll; int Case,n,m,i,ce,x;ll ans; struct E{int x,y;E(){}E(int _x,int _y){x=_x,y=_y;}}e[200010]; inline bool cmp(const E&a,const E&b){return a.x<b.x;} int main(){ scanf("%d",&Case); while(Case--){ priority_queue<ll,vector<ll>,greater<ll> >A,B,C; scanf("%d%d",&n,&m); ce=0; while(n--){ scanf("%d",&x); e[++ce]=E(x,0); } while(m--){ scanf("%d",&x); e[++ce]=E(x,1); } sort(e+1,e+ce+1,cmp); ans=0; for(i=1;i<=ce;i++){ ll x=e[i].x; if(e[i].y==0){ if(!C.empty()){ ll t=C.top(); C.pop(); ans+=x+t; }else if(!B.empty()){ ll t=B.top(); if(t+x<0){ B.pop(); ans+=x+t; A.push(-t-x-x); }else A.push(-x); }else A.push(-x); }else{ if(!A.empty()){ ll t=A.top(); A.pop(); ans+=x+t; B.push(-t-x-x); }else C.push(-x); } } printf("%lld\n",ans); } }
以上是关于可撤销贪心的主要内容,如果未能解决你的问题,请参考以下文章
Contig|scaffold|N50|L50|NG50|贪心算法|de bruiji graph|
Swift3.0学习实践-一个简单的画板(七色轨迹可撤销可清除带橡皮擦)