Luogu 1484 种树
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 种树的更多相关文章
- luogu 1484\1792 种树 奇怪的贪心可反悔
1484 种树 此版本是线性的,那么根据链表维护即可: 构建新点,点的左右分别是原整个区间的前驱及后继,再正常维护即可 注意两个版本的维护有所不同 第二个版本的维护直接将左右两点删除 1792 种树2 ...
- luogu P1250 种树
我来总结一下最常用的两种办法 1.贪心 2.差分约束 那么我们先来讲,贪心版<种树> 大家可能知道有一个题和这个类似,那个是钉钉子而这个是种树 我们可以借用钉钉子的思路来想,首先这个是让你 ...
- Luogu P1484 种树
这道题目还是比较简单的 首先题目的意思就让我们很轻易地想到DP 我们设f[i][j]表示前i个坑中种j棵树的最大利益,则有: f[i][j]=max(f[i-1][j],f[i-2][j-1]+a[i ...
- dp题
1.luogu 1484种树 50分思路:dp,但是数据规模过大没法dp选择奇怪贪心 dp方程 到i坑种j树 dp[i][j]=max(dp[i-1][j],dp[i-2][j-1]) 100分思路: ...
- Guard Duty (medium) Codeforces - 958E2 || (bzoj 2151||洛谷P1792) 种树 || 编译优化
https://codeforces.com/contest/958/problem/E2 首先求出N个时刻的N-1个间隔长度,问题就相当于在这些间隔中选K个数,相邻两个不能同时选,要求和最小 方法1 ...
- Luogu P5564 [Celeste-B]Say Goodbye (多项式、FFT、Burnside引理、组合计数)
题目链接 https://www.luogu.org/problem/P5564 题解 这题最重要的一步是读明白题. 为了方便起见下面设环长可以是\(1\), 最后统计答案时去掉即可. 实际上就相当于 ...
- [luogu]P1133 教主的花园[DP]
[luogu]P1133 教主的花园 ——!x^n+y^n=z^n 题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会 ...
- P1250 种树(差分约束 / 贪心)
题目描述 一条街的一边有几座房子.因为环保原因居民想要在路边种些树.路边的地区被分割成块,并被编号成1-N.每个部分为一个单位尺寸大小并最多可种一棵树.每个居民想在门前种些树并指定了三个号码B,E,T ...
- 帝国の狂欢(种树)(可撤销DP)
题目描述 马上就要开学了!!! 为了给回家的童鞋们接风洗尘,HZOI帝国的老大决定举办一场狂欢舞会. 然而HZOI帝国头顶上的HZ大帝国十分小气,并不愿意给同学们腾出太多的地方.所以留给同学们开par ...
随机推荐
- Alex and broken contest CodeForces - 877A
/* Name: Copyright: Author: Date: 2018/5/2 10:45:16 Description: 要求出现一个朋友的名字,仅一次 */ #include <ios ...
- 使用手势对UIImageView进行缩放、旋转和移动(转)
原文地址:http://blog.csdn.net/crazy_frog/article/details/8664108 // 添加所有的手势 - (void) addGestureRecognize ...
- Codeforces Round #259(div2)C(数学期望)
数学题. 关键是求最大值为k时有多少种情况,结果是kn-(k-1)n-1.可以这么想:每一次都从1至k里选,共kn种,这里需要再减去每一次都从1至k-1里面选的情况.当然也可以分类计数法:按出现几次k ...
- 自编jQuery插件实现模拟alert和confirm
现在绝大多数网站都不用自带的alert和confirm了,因为界面太生硬了.因此这个插件就这样产生了自己定制一个的想法...... 啥也不说,先上图,有图有真相 :) 现在绝大多数网站都不用自带的al ...
- MD5加密 及获得密码盐
MD5加密 及获得密码盐 using System; using System.Collections.Generic; using System.Configuration; using Syste ...
- 在struts2中配置自定义拦截器放行多个方法
源码: 自定义的拦截器类: //自定义拦截器类:LoginInterceptor ; package com.java.action.interceptor; import javax.servlet ...
- rails登录后跳转到登录前的路径
# 重定向到存储的地址或默认地址 def redirect_back_or(default) redirect_to(session[:forwarding_url] || default) sess ...
- php大型网站如何提高性能和并发访问
一.大型网站性能提高策略: 大型网站,比如门户网站,在面对大量用户访问.高并发请求方面,基本的解决方案集中在这样几个环节:使用高性能的服务器.高性能的数据库.高效率的编程语言.还有高性能的Web容器. ...
- Celery-4.1 用户指南: Calling Tasks(调用任务)
基础 本文档描述 Celery 中任务实例和 Canvas 使用的统一 “Calling API”. API 中定义了一个执行选项的标准集,以及三个方法: - apply_async(args[, k ...
- python 函数对象、函数嵌套、名称空间与作用域、装饰器
一 函数对象 一 函数是第一类对象,即函数可以当作数据传递 1 可以被引用 2 可以当作参数传递 3 返回值可以是函数 3 可以当作容器类型的元素 二 利用该特性,优雅的取代多分支的if def fo ...