可撤销贪心

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);
  }
}

原文地址:https://www.cnblogs.com/uid001/p/10886918.html

时间: 2024-10-08 20:45:54

可撤销贪心的相关文章

WQS二分题集

WQS二分,一种优化一类特殊DP的方法. 很多最优化问题都是形如“一堆物品,取与不取之间有限制.现在规定只取k个,最大/小化总收益”. 这类问题最自然的想法是:设f[i][j]表示前i个取j个的最大收益,转移即可.复杂度O(n^2). 那么,如果在某些情况下,可以通过将问题稍作转化,变成一个不强制选k个的DP,而最后DP出来的最优解一定正好选了k个,那么问题就会简化很多. WQS二分就是基于这个思想. 首先考虑建一个二维坐标系,x轴是选的数的个数,y轴是最大收益,如果这个x-y图像有凸性,那么就

《信奥一本通》提高版—简要题解

<信奥一本通>提高版-简要题解 贪心 活动安排: 按右端点排序,因为越早结束越好. 然后从1扫到n,每次比较当前位置线段的左端点是否大于上一个选的线段的右端点.如果大于,那么ans++,将上一个选的线段的右端点更新为当前线段的右端点:如果小于,那什么都不用做.因为选上一条一定比选当前这一条更优(结束时间更早). 种树 按右端点排序,对于每个区间的需求,从右端往左端扫,只要没种到树的就种,ans++. 因为要使前面的需求尽量与后面的需求重叠,从而使树的数量最少 喷水装置 观察+画图发现对于一个圆

【uva 1615】Highway(算法效率--贪心 区间选点问题)

题意:给定平面上N个点和一个值D,要求在x轴上选出尽量少的点,使得对于给定的每个店,都有一个选出的点离它的欧几里德距离不超过D. 解法:先把问题转换成模型,把对平面的点满足条件的点在x轴的直线上可得到一个个区间,这样就是选最小的点覆盖所有的区间的问题了.我之前的一篇博文有较详细的解释:关于贪心算法的经典问题(算法效率 or 动态规划).代码实现我先空着.挖坑~

【贪心+Treap】BZOJ1691-[Usaco2007 Dec]挑剔的美食家

[题目大意] 有n头奶牛m种牧草,每种牧草有它的价格和鲜嫩度.每头奶牛要求它的牧草的鲜嫩度要不低于一个值,价格也不低于一个值.每种牧草只会被一头牛选择.问最少要多少钱? [思路] 显然的贪心,把奶牛和牧草都按照鲜嫩度由大到小排序,对于每奶牛把鲜嫩度大于它的都扔进treap,然后找出后继. 不过注意后继的概念是大于它且最小的,然而我们这里是可以等于的,所以应该是找cow[i].fresh-1的后继,注意一下…… 1 #include<iostream> 2 #include<cstdio&

POJ1017 Packets(贪心算法训练)

Time Limit: 1000MS          Memory Limit: 10000K          Total Submissions: 51306          Accepted: 17391 Description A factory produces products packed in square packets of the same height h and of the sizes 1*1, 2*2, 3*3, 4*4, 5*5, 6*6. These pro

ZOJ 3946 Highway Project 贪心+最短路

题目链接: http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3946 题解: 用dijkstra跑单元最短路径,如果对于顶点v,存在一系列边(ui,v)使得dis[v]最小(dis[v]表示0到v的距离).这些边能且只能选一条,那么我们自然应该选cost最小的那个边了. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #inc

CoderForce 140C-New Year Snowmen(贪心)

题目大意:有n个已知半径的雪球.堆一个雪人需要三个尺寸不同的雪球,问用这些雪球最多能堆多少个雪人? 题目分析:先统计一下每种尺寸的球的个数,从三种最多的种类中各取出一个堆成雪人,这样贪心能保证的到的数目最多. 代码如下: # include<iostream> # include<map> # include<vector> # include<cstdio> # include<queue> # include<algorithm>

计蒜客 跳跃游戏(贪心)

给定一个非负整数数组,假定你的初始位置为数组第一个下标.数组中的每个元素代表你在那个位置能够跳跃的最大长度. 请确认你是否能够跳跃到数组的最后一个下标. 例如: A = [2,3,1,1,4], return ture A = [3,2,1,0,4], return false. 格式: 第一行输入一个正整数n,接下来的一行,输入数组A[n].如果能跳到最后一个下标,输出"true",否则输出"false" 样例1 ????输入:???? ????????5 ???

BZOJ 2525 [Poi2011]Dynamite 二分+树形贪心

题意: n个点,一棵树,有些点是关键点,可以将m个点染色. 求所有关键点到最近的被染色点的距离的最大值最小. 解析: 反正从这道题我是学了一种做题思路? 大爷讲课的时候说的:一般选择某些点的代价相同的话都是贪心,代价不同的话一般都是DP. 想想也挺对的,不过就是没有感悟到过? 反正这题考试的时候我是直接D了贪心的- -! 忘了为啥D了. 显然最大值最小我们需要二分一下这个值. 然后接下来我们从下往上扫整棵树. 节点的状态有几个? 第一种是 子树内没有不被覆盖的关键点,并且子树中有一个节点的贡献可