【洛谷】【堆+贪心】P1484 种树

【题目描述:】

cyrcyr今天在种树,他在一条直线上挖了n个坑。这n个坑都可以种树,但为了保证每一棵树都有充足的养料,cyrcyr不会在相邻的两个坑中种树。而且由于cyrcyr的树种不够,他至多会种k棵树。假设cyrcyr有某种神能力,能预知自己在某个坑种树的获利会是多少(可能为负),请你帮助他计算出他的最大获利。

【输入格式:】

第一行,两个正整数n,k。

第二行,n个正整数,第i个数表示在直线上从左往右数第i个坑种树的获利。

【输出格式:】

输出1个数,表示cyrcyr种树的最大获利。

输入样例#1:
6 3
100 1 -1 100 1 -1
输出样例#1:
200

输入输出样例

【算法分析:】

这时一道贪心的题目:

对于一个树坑i,有两种状态:种树或者不种树

当选择树坑i种树时,获利为a[i]

而也可以选择在(i - 1)和(i + 1)两个位置种树,所以将a[i]更新成a[i - 1] + a[i + 1] - a[i]

利用大根堆每次寻找最大值,并将更改后的值再次push进堆里

如果选择i后又选择了(i - 1)和(i + 1),更新时 - a[i]的操作就显得不可或缺了= =

利用堆优化后的算法复杂度为O(k log2 n)

【代码:】

 1 //种树
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<vector>
 7
 8 #define pii pair<int, int>
 9 #define mkp make_pair
10 #define fi first
11 #define se second
12 using namespace std;
13
14 const int MAXN = 500000 + 1;
15
16 priority_queue<pii> q;
17
18 int n, k;
19 int a[MAXN], l[MAXN], r[MAXN];
20 bool tree[MAXN];
21 long long ans;
22
23 int main() {
24     scanf("%d%d", &n, &k);
25     for(int i = 1; i <= n; i++) {
26         scanf("%d", &a[i]);
27         q.push(mkp(a[i], i));
28         l[i] = i - 1, r[i] = i + 1;
29     }
30     r[0] = 1, l[n + 1] = n;
31     while(k--) {
32         while(tree[q.top().se]) q.pop();
33         pii tmp = q.top();
34         q.pop();
35         if(tmp.fi <= 0) break;
36         ans += tmp.fi;
37         int pos = tmp.se;
38         a[pos] = a[l[pos]] + a[r[pos]] - a[pos];
39         tmp.fi = a[pos];
40         tree[l[pos]] = tree[r[pos]] = 1;
41         l[pos] = l[l[pos]], r[l[pos]] = pos;
42         r[pos] = r[r[pos]], l[r[pos]] = pos;
43         q.push(tmp);
44     }
45     printf("%lld\n", ans);
46 }

原文地址:https://www.cnblogs.com/devilk-sjj/p/9031358.html

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

【洛谷】【堆+贪心】P1484 种树的相关文章

升序堆和降序堆(优先队列) 洛谷1801

1 // 洛谷1801 2 // 一个升序堆,一个降序堆 3 // 降序堆维护序列的前i个最小值 4 // 插如元素的时候,如果x小于降序堆最大值,则替换,并将最大值插入升序堆:否则,直接插入升序堆 5 // 每次输出升序堆的最小值即可 6 7 8 #include <bits/stdc++.h> 9 using namespace std; 10 #define LL long long 11 typedef pair<int,int> pii; 12 const int inf

洛谷P1168 中位数 堆

洛谷P1168 中位数   堆 求a[ 1 ] --a[ 1 ] 的中位数 ,a[ 1 ]--a[ 3 ] 的中位数 a[ 1 ]--a[ 5 ] 的中位数 题解1.假设我们已知 a[ 1 ]--a[ i ] 的中位数 (i&1) 此时我们求 a[ 1 ]--a[ i+2 ] 的中位数 那么我们可以把比他大的划到一份中,比他小的划到一份中,如果两份数的个数相同,则其仍然是中位数2.如果不同,比如说 big > small 那我们就把比他大的数 作为中位数 ans 到比中位数小的数中因为原本s

洛谷P1969 积木大赛 贪心 差分

洛谷P1969 积木大赛 贪心 考虑差分 对区间 [l,r]+1 在差分数组上相当于 d[ l ]++ ; d[ r+1 ]-- ; 那么你得到原数组的差分数组后 当d[ i ] = x 则你需要 对 以 i 为左端点 右端点未知的一个区间加x次且这x加的可能不是同一个区间 所以最后只要将差分数组中所有正数加上去就行了 同样其实也可以用负数算的,但是负数算的话,要加上 d[ n+1 ] 即 a[ n+1 ] - a[ n ] 或者另一种思路对于一段上升(不下降)区间,我们在搭最高层时可以把下面一

洛谷P1080 国王游戏 高精度 贪心 数学推公式

洛谷P1080 国王游戏        数学推公式      高精度    贪心 然而这并不是我打出来的,抄题解... 将左手与右手的乘积从小到大排序,然后计算求最大值即可.(需要高精度) 证明: 1)知道,如果相邻的两个人交换位置,只会影响到这两个人的值,不会影响他人 2)假设相邻的两个人i, i + 1.设A[i] B[i] <= A[i + 1] B[i + 1],i之前所有人的左手乘积为S. 则,ans1 = max{S / B[i], S * A[i] / B[i + 1]} 若交换

洛谷P2294 [HNOI2005]狡猾的商人 ,神奇做法——贪心

HNOI2005狡猾的商人,洛谷链接 原题入口 看到大牛都是写的差分约束或带权并查集,本蒟蒻都不太会(还是用差分约束过了的QAQ),但是想出一种贪心的策略,运用神奇的优先队列实现.思路是:先按左端点为第一排序关键字,再排右端点.之后就开始两两比较,如果左端点相等,就比较右端点,如果相等,就比较值,如果值不同,就直接输出false,否则输出true,如果右端点不等,就把相同的部分抵消掉,把新的区间再压入优先队列.直到不能操作,就输出true.下附代码: 1 #include<queue> 2 #

洛谷 P1223 排队接水(贪心,桶排序)

此题为洛谷普及试炼场的一道水题.... 题目链接:https://www.luogu.org/problem/show?pid=1223 题目描述 有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小. 输入输出格式 输入格式: 输入文件共两行,第一行为n:第二行分别表示第1个人到第n个人每人的接水时间T1,T2,-,Tn,每个数据之间有1个空格. 输出格式: 输出文件有两行,第一行为一种排队顺序,即1到n的一种排列:第二行为

[洛谷201704R1]开心派对小火车

OJ题号:洛谷P3697 思路: 贪心.首先从起点出发,开特急电车,对于每一个特急车站$s_{i}$,分别下一次车,计算从当前车站$s_{i}$出发坐各停电车在指定时限内$t$最远能够到达的车站$r_{i}$,并保证这个$r_{i}$不会超过$s_{i+1}$.将得到的站点$r_{i}$放入一个大根堆中,堆中的每个元素记录两个值,第一个用来保存如果在当前站点开通快速电车,从当前站点坐快速电车总共能到达的站的个数:第二个用来保存当前站的编号$r_i$.最后不断地从堆中挑选最优的站,重复拓展到新的站

洛谷教主花园dp

洛谷-教主的花园-动态规划 题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值. 教主最喜欢3种树,这3种树的高度分别为10,20,30.教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高. 输入输出格式 输入格式: 输入文件garden.in的第1行为一个正整数n,表示需要种的

洛谷P1848 [USACO12OPEN]书架Bookshelf

当农夫约翰闲的没事干的时候,他喜欢坐下来看书.多年过去,他已经收集了 N 本书 (1 <= N <= 100,000), 他想造一个新的书架来装所有书. 每本书 i 都有宽度 W(i) 和高度 H(i).书需要按顺序添加到一组书架上:比如说,第一层架子应该包含书籍1 ... k,第二层架子应该以第k + 1本书开始,以下如此.每层架子的总宽度最大为L(1≤L≤1,000,000,000).每层的高度等于该层上最高的书的高度,并且整个书架的高度是所有层的高度的总和,因为它们都垂直堆叠. 请帮助农

[洛谷]P3613 睡觉困难综合征

题目大意:给出一棵n个点的树,每个点有一个运算符(与.或.异或)和一个数,支持两种操作,第一种修改一个点的运算符和数,第二种给出x,y,z,询问若有一个0~z之间的数从点x走到点y(简单路径),并且对路径上经过的点做对应的运算,最终最大能是多少.(n,操作数<=100,000,数字在[0,2^64)之间) 思路:洛谷改编NOI的一道神题,树剖/LCT维护若一开始全是0/全是1,经过一条链后各位会变成什么,用位运算合并信息,然后每个询问,从高位往低位贪心,每次取0和1中经过这条链后得到的较大值,若