基准时间限制:1 秒 空间限制:131072 KB 分值: 320 难度:7级算法题
 收藏
 取消关注
又到了诺德县的百姓孝敬夹克大老爷的日子,带着数量不等的铜板的村民准时聚集到了村口。

夹克老爷是一位很"善良"的老爷,为了体现他的仁慈,有一套特别的收钱的技巧。

1、让所有的村民排成一队,然后首尾相接排成一个圈。

2、选择一位村民收下他的铜钱,然后放过他左右两边的村民。

3、让上述三位村民离开队伍,并让左右两边的其他村民合拢起来继续围成一个圈。

4、重复执行2、3直到村民全部离开。

夹克老爷的家丁早早的组织村民排成一队并清点了村民人数和他们手里的铜钱数量。

作为夹克老爷的首席师爷,你要负责按照夹克老爷的收钱技巧完成纳贡的任务。

聪明的你当然知道夹克老爷并不像他表现出来的那样仁慈,能否收到最多的钱财决定了你是否能够继续坐稳首席师爷的位置。

今年村民的人数是N,恰巧是3的倍数。





提示:第2步选择村民时不需要按照任何顺序,你可以选择任何一位仍然在队伍里的村民收取他手中的钱财并放走他两侧的村民(这就意味着你无法同时收取到这两位的铜钱了)
Input
第一行1个整数N(3 <= N <= 10^5 - 1, N % 3 == 0)
第2 - N + 1行:每行1个数对应村民i手中的铜钱。(0 <= m[i] <= 10^9)
Output
一个整数,说明在夹克老爷的收钱规则下你最多能够为夹克老爷搜刮到多少铜钱
Input示例
6
6
2
3
4
5
9
Output示例
13

问题等价于N长的数组中抽取N/3个不相邻的值使得和最大(首尾也不能同时取)

普通的dp方法复杂度n^2会TLE
用贪心,类似最大M子段和的方式
初始全部数字可选状态,进优先队列,弹出最大值,结果中加上选中的最大值,删除最大值左右两边的值,将最大值位置的值修改为左右两边的和减去中间的数重新进入优先队列,循环处理直到拿到要求的数据个数。

以上是官方题解。。。头一次用优先队列做这种题,“结果中加上选中的最大值,删除最大值左右两边的值,将最大值位置的值修改为左右两边的和减去中间的数重新进入优先队列,循环处理直到拿到要求的数据个数。”这块太巧妙了,直接把算法的时间复杂度搞到了O(n)。
代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#include <queue>
#pragma warning(disable:4996)
using namespace std; #define impossible -1*(1e9+7) struct no
{
long long val;
int pos; friend bool operator<(no n1, no n2)
{
return n1.val < n2.val;
}
}node[100005]; int n;
long long val[100005]; int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout); int i, k, temp, out;
unsigned long long sum;
no n_temp;
priority_queue<no>q; scanf("%d", &n); for (i = 0; i < n; i++)
{
scanf("%d", &temp);
node[i].val = temp;
node[i].pos = i;
q.push(node[i]); val[i] = temp;
} k = 0;
sum = 0;
out = n / 3;
while (true)
{
n_temp = q.top();
if (n_temp.val <= 0)
break;
if (val[n_temp.pos] != impossible)
{
q.pop();
sum += n_temp.val; int le = n_temp.pos;
int ri = n_temp.pos;
while (val[(le - 1 + n) % n] == impossible)
{
le--;
}
while (val[(ri + 1 + n) % n] == impossible)
{
ri++;
} no nn_temp;
nn_temp.val = val[(le - 1 + n) % n] + val[(ri + 1 + n) % n ] - n_temp.val;
nn_temp.pos = n_temp.pos; q.push(nn_temp); val[n_temp.pos] = nn_temp.val;
val[(le - 1 + n) % n] = impossible;
val[(ri + 1 + n) % n] = impossible; k++;
}
else
{
q.pop();
}
if (k == out)
break;
} printf("%lld\n", sum);
//system("pause");
return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

51nod 1380:夹克老爷的逢三抽一的更多相关文章

  1. 51nod 1380"夹克老爷的逢三抽一"(贪心+set)

    传送门 •参考资料 [1]:51Nod-1380-夹克老爷的逢三抽一 •题意 从长度为 n 的数组中抽取 $\frac{n}{3}$ 个不相邻的值使得加和最大(首尾也不能同时取) •题解 贪心选择当前 ...

  2. 51Nod 1380 夹克老爷的逢三抽一

    Description 一开始有一个环,可以选择删除一个元素获得他的权值,同时删除与它相邻的两个元素,其他元素重新形成环,问能获得的最大价值. Sol 堆+贪心. 一开始从堆中加入所有元素,然后取出一 ...

  3. 51nod1380 夹克老爷的逢三抽一

    问题等价于选出$n / 3$个不相邻元素是权值和最大 这是一个经典贪心问题,同种树,拿堆维护即可,复杂度$O(n \log n)$ #include <queue> #include &l ...

  4. 51nod 1378 夹克老爷的愤怒(树型dp+贪心)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1378 题意: 思路:要想放得少,尽量放在叶子节点处,叶子节点处点比较多. ...

  5. 51Nod 1378 夹克老爷的愤怒

    Description 一棵树,可以进行染色,被染色的点可以控制与它距离不超过 \(k\) 的所有点,问控制整棵树最少需要染几个点. Sol 贪心. 记录一下最深的未染色点和最浅的染色点,判断一下能否 ...

  6. 51nod 1378:夹克老爷的愤怒 很好玩的一道树状dp

    1378 夹克老爷的愤怒 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  取消关注 夹克老爷逢三抽一之后,由于采用了新师爷的策略,乡民们叫苦不堪,开始组织 ...

  7. 逢三退一(boolean数组的使用)

    package com.hanqi.count; // 逢三退一 输出留到最后值的索引; public class Count1 { //主方法 public static void main(Str ...

  8. 51nod 1625 夹克爷发红包

    题目链接戳这里 题意是有一个赋有非负数的矩阵,每次可以将某一行or某一列替换成某个数值,可以替换<=k次,问如何替换能使得矩阵总和最大,输出最大值. 一开始想的是简单的贪心:比如找当前收益最大的 ...

  9. 胡小兔的OI日志3 完结版

    胡小兔的 OI 日志 3 (2017.9.1 ~ 2017.10.11) 标签: 日记 查看最新 2017-09-02 51nod 1378 夹克老爷的愤怒 | 树形DP 夹克老爷逢三抽一之后,由于采 ...

随机推荐

  1. linux 镜像备份工具rsnyc

    1.本地拷贝文件nohup rsync -avzh /data/wwwroot/xhprof/* /mnt/xhprof/ &2.更改文件夹名称mv /data/wwwroot/xhprof ...

  2. SystemC中文教程一

    SystemC是什么 首先, SystemC不是一门新的语言,而是基于C++开发的library:因此,你所熟悉的C++知识都可以在SystemC建模时使用:理论上来说,SystemC library ...

  3. Redis常用命令操作

    字符串类型: * 存储:set key value * 获取:get key * 无值返回nil * 删除:del key 哈希类型 hash: * 存储:hset key field value * ...

  4. PTA的Python练习题(十一)

    从 第4章-3 猴子吃桃问题 继续 1. a=eval(input()) def count(n): b=1 for i in range(n-1): b=(b+1)*2 return b print ...

  5. Python组合类型笔记

    Python中常用的三种组合数据类型,分别是: - 集合类型 - 序列类型 - 字典类型 1. 集合类型: -集合用大括号{}表示,元素间用逗号分隔 -建立集合类型用{}或set() -建立空集合类型 ...

  6. java记录3--异常

    异常的分类 1.Error 由java虚拟机生成并抛出,包括动态链接失败,虚拟机错误等等,JAVA程序无法对此错误 try { //可能出现异常的代码块 } catch(exception1 ) { ...

  7. [Android实例] Android网络收音机项目(内含源码)

    ======================帖子内容===================================最近喜欢听广播,但是搜索了一下,苦于网上没有Android的网络收音机项目的例 ...

  8. 解决IE打开时,弹出的提示调用active的问题,阻止js运行。

    在html和head中间加上: <!-- saved from url=(0014)about:internet -->

  9. lib文件和dll文件

    一. 简介 1.1 C++两种库文件 lib包含了函数所在的dll文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的dll提供,称为动态链接库dynamic link library. ...

  10. Python - ORM(数据库相关)

    1. 概念 目标:类/对象操作 -> SQL语句 -> DB API -> 再在数据库中执行.ORM做前两部,因为ORM本身无法操作数据库.参考:https://baike.baid ...