Luogu 1792 算是双倍经验。

我们考虑对于一个点,我们要么选它,要么选它周围的两个点。

所以我们考虑用一个堆来维护,每次从堆顶取出最大值之后我们把它的权值记为:它左边的权值加上它右边的权值减去它自己的权值。即$a_{pos} = a_{l(pos)} + a_{r(pos)} - a_{pos}$。然后把它丢到堆里去。

这样子如果下次取出来这个值就相当于不选原来选过的那个点,而改选它旁边的两个点,而这样选的总的点数也是一样的,这个过程也可以扩展到一个区间,所以这样子可以求出最优解。

对于那些取出来的点的两边的点,我们下次在取出来的时候不应该再计算贡献,所以记一个$vis$。

这个“左边的点”和“右边的点”可以用链表维护。

注意到本题中不一定选满$k$个,所以当取出来的堆顶权值为负的时候直接$break$掉,而在Luogu1792中一定要选满$k$个。

时间复杂度$O(klogn)$。

Code:

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll; const int N = 5e5 + ; int n, K, nxt[N], pre[N];
ll a[N];
bool vis[N]; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} struct Node {
ll val; int pos; Node(ll v = , int p = ) {val = v, pos = p;} friend bool operator < (const Node &x, const Node &y) {
return x.val < y.val;
} };
priority_queue <Node> Q; inline void del(int p) {
nxt[pre[p]] = nxt[p];
pre[nxt[p]] = pre[p];
vis[p] = ;
} int main() {
read(n), read(K);
for(int i = ; i <= n; i++) {
read(a[i]);
nxt[i] = i + , pre[i] = i - ;
Q.push(Node(a[i], i));
} ll ans = 0LL;
for(; K--; ) {
for(; vis[Q.top().pos]; Q.pop());
Node out = Q.top(); Q.pop();
if(out.val < ) break;
int x = pre[out.pos], y = nxt[out.pos];
ans += out.val;
Q.push(Node(a[out.pos] = a[x] + a[y] - out.val, out.pos));
del(x), del(y);
} printf("%lld\n", ans);
return ;
}

Luogu 1484 种树的更多相关文章

  1. luogu 1484\1792 种树 奇怪的贪心可反悔

    1484 种树 此版本是线性的,那么根据链表维护即可: 构建新点,点的左右分别是原整个区间的前驱及后继,再正常维护即可 注意两个版本的维护有所不同 第二个版本的维护直接将左右两点删除 1792 种树2 ...

  2. luogu P1250 种树

    我来总结一下最常用的两种办法 1.贪心 2.差分约束 那么我们先来讲,贪心版<种树> 大家可能知道有一个题和这个类似,那个是钉钉子而这个是种树 我们可以借用钉钉子的思路来想,首先这个是让你 ...

  3. Luogu P1484 种树

    这道题目还是比较简单的 首先题目的意思就让我们很轻易地想到DP 我们设f[i][j]表示前i个坑中种j棵树的最大利益,则有: f[i][j]=max(f[i-1][j],f[i-2][j-1]+a[i ...

  4. dp题

    1.luogu 1484种树 50分思路:dp,但是数据规模过大没法dp选择奇怪贪心 dp方程 到i坑种j树 dp[i][j]=max(dp[i-1][j],dp[i-2][j-1]) 100分思路: ...

  5. Guard Duty (medium) Codeforces - 958E2 || (bzoj 2151||洛谷P1792) 种树 || 编译优化

    https://codeforces.com/contest/958/problem/E2 首先求出N个时刻的N-1个间隔长度,问题就相当于在这些间隔中选K个数,相邻两个不能同时选,要求和最小 方法1 ...

  6. Luogu P5564 [Celeste-B]Say Goodbye (多项式、FFT、Burnside引理、组合计数)

    题目链接 https://www.luogu.org/problem/P5564 题解 这题最重要的一步是读明白题. 为了方便起见下面设环长可以是\(1\), 最后统计答案时去掉即可. 实际上就相当于 ...

  7. [luogu]P1133 教主的花园[DP]

    [luogu]P1133 教主的花园 ——!x^n+y^n=z^n 题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会 ...

  8. P1250 种树(差分约束 / 贪心)

    题目描述 一条街的一边有几座房子.因为环保原因居民想要在路边种些树.路边的地区被分割成块,并被编号成1-N.每个部分为一个单位尺寸大小并最多可种一棵树.每个居民想在门前种些树并指定了三个号码B,E,T ...

  9. 帝国の狂欢(种树)(可撤销DP)

    题目描述 马上就要开学了!!! 为了给回家的童鞋们接风洗尘,HZOI帝国的老大决定举办一场狂欢舞会. 然而HZOI帝国头顶上的HZ大帝国十分小气,并不愿意给同学们腾出太多的地方.所以留给同学们开par ...

随机推荐

  1. AngularJS-webapp($q)

    $q延迟加载: 当一个数据需要请求多次,后面一个数据需要前面请求的数据时,我们就可以通过延迟加载进行数据传递 如下代码: 首先:我们需要得到职位信息: { "id": " ...

  2. python编程实例-dmidecode系统信息搜集

    #!/usr/bin/env python from subprocess import PIPE,Popen def getDmi(): p = Popen(['dmidecode'],stdout ...

  3. Ajax做日期选择

    1.主页面 引入JS Jquery bootstrap 包 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN& ...

  4. (转)SPFA算法

    原文地址:http://www.cnblogs.com/scau20110726/archive/2012/11/18/2776124.html 粗略讲讲SPFA算法的原理,SPFA算法是1994年西 ...

  5. 【1】String,StringBuffer,StringBuillder的底层结构研究

    一:StringBuffer的底层 (1)线程安全的字符串操作类 (2)通过synchronized关键字声明同步方法,保证多线程环境下数据安全 @Override public synchroniz ...

  6. bzoj 2744 [HEOI2012]朋友圈——补图!+匈牙利算法

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2744 求最大的团<==>补图(有边的变成没边.没边的变成有边)的最大独立集! A ...

  7. Poj 2488 A Knight's Journey(搜索)

    Background The knight is getting bored of seeing the same black and white squares again and again an ...

  8. PAT 垃圾箱分布(30分)dijstra

    垃圾箱分布 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾 ...

  9. mongodb collection method

    https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/ db.coll_test.getIndexes()# ...

  10. [置顶] if语句的陷阱

    if else if是只要有满足条件的,就不再对之后的else if进行判断 #include<stdio.h> void main() { char a=0; if(a==0) { a= ...