【NOIP2015模拟11.2】有趣的有趣的家庭菜园

题面



思路一

暴力 \(30\) 分!

很容易打,但是要注意:

  • 开 \(\texttt{long long}\)
  • 是非严格高于(等于是被允许的)

思路二

发现 \(i\) 能收获的条件是只要他为其中一侧的最大值

那么我们设 \(f_i\) 表示 \(1..i\) 中必选 \(i\) 的答案,\(g_i\) 表示 \(i..n\) 中必选 \(i\) 的答案

那么答案就是 \(\max_{i=1}^n{f[i]+g[i]-val[i]}\),其中 \(val[i]\) 表示 \(i\) 草收获果实的贡献。

因为根据 \(f,g\) 的定义可得 \(i\) 处两者都算了,所以就减去重复的贡献

那么考虑怎么求 \(f,g\)

既然两者一个是顺着,一个是倒着,那么我们不妨讨论 \(f\),\(g\) 同理

思考 \(i\) 从 \(j\) 处转移过来,\((i,j)\) 间比 \(i\) 高的草都要除掉

那么 \(f_i = \max(f_j - \sum_{k=j+1}^{i-1} cost_k·[h_k > h_i])(0 \leq j < i)\)

\(cost_k\) 为除掉 \(k\) 所需的费用

它显然是 \(O(n^3)\) 的

我们要考虑优化

思考我们是如何进行转移的?

感性的理解,我们找到 \(j\),把 \(j\) 到 \(i\) 间比 \(i\) 高的草都删除再转移到 \(i\)

那么我们能不能考虑一次性找到最大的 \(f_j - \sum_{k=j+1}^{i-1} cost_k·[h_k > h_i]\)

发现限制条件是 \(h_k > h_i\)

也就是说从左一次往右时 \(h_i\) 会影响比他矮的节点,\(f_j - \sum_{k=j+1}^{i-1} cost_k·[h_k > h_i]\) 就是开区间 \((i..j)\) 中比 \(j\) 高的所有草费用之和

即遇到一个 \(h_i\) 时就算它的影响

于是我们可以用线段树维护,对草的高度先离散化,再对高度建一颗线段树

对于当前点 \(i\),先找线段树 \([1..h_i]\) 中权值最大的点更新 \(f_i\)

然后让线段树中 \([1..h_i-1]\) 的值减去 \(cost_i\)

最后把 \(f_i\) 插入线段树中 \(h_i\) 的位置

终了统计一下答案

正好温习一下线段树的区间加,区间最值,单点修改

记得打懒标记哦!!

\(Code\)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL; const int N = 1e5 + 5;
int n;
LL seg[N << 2] , tag[N << 2] , f[N] , g[N] , ans; struct node{
int hign , h , p , c , id;
}a[N]; inline bool cmp(node x , node y){return x.hign < y.hign;}
inline bool cmp1(node x , node y){return x.id < y.id;} inline void pushup(int k){seg[k] = max(seg[k << 1] , seg[k << 1 | 1]);}
inline void pushdown(int k)
{
if (tag[k] != 0)
{
seg[k << 1] += tag[k];
tag[k << 1] += tag[k];
seg[k << 1 | 1] += tag[k];
tag[k << 1 | 1] += tag[k];
tag[k] = 0;
}
} inline void update(int x , LL y , int l , int r , int k)
{
if (l == r && l == x)
{
seg[k] = max(seg[k] , y);
return;
}
pushdown(k);
int mid = (l + r) >> 1;
if (x <= mid) update(x , y , l , mid , k << 1);
else update(x , y , mid + 1 , r , k << 1 | 1);
pushup(k);
} inline void change(int x , int y , LL v , int l , int r , int k)
{
if (x <= l && r <= y)
{
tag[k] += v;
seg[k] += v;
return;
}
pushdown(k);
int mid = (l + r) >> 1;
if (x <= mid) change(x , y , v , l , mid , k << 1);
if (y > mid) change(x , y , v , mid + 1 , r , k << 1 | 1);
pushup(k);
} inline LL query(int x , int y , int l , int r , int k)
{
if (x <= l && r <= y) return seg[k];
pushdown(k);
LL res = -1e18;
int mid = (l + r) >> 1;
if (x <= mid) res = max(res , query(x , y , l , mid , k << 1));
if (y > mid) res = max(res , query(x , y , mid + 1 , r , k << 1 | 1));
return res;
} int main()
{
freopen("herbary.in" , "r" , stdin);
freopen("herbary.out" , "w" , stdout);
scanf("%d" , &n);
for(register int i = 1; i <= n; i++) scanf("%d%d%d" , &a[i].hign , &a[i].p , &a[i].c) , a[i].id = i;
sort(a + 1 , a + n + 1 , cmp);
a[1].h = 1;
int s = 1;
for(register int i = 2; i <= n; i++)
{
if (a[i].hign == a[i-1].hign) a[i].h = a[i-1].h;
else a[i].h = ++s;
}
sort(a + 1 , a + n + 1 , cmp1); memset(seg , 0 , sizeof seg);
memset(tag , 0 , sizeof tag);
for(register int i = 1; i <= n; i++)
{
f[i] = query(1 , a[i].h , 1 , s , 1) + a[i].p;
update(a[i].h , f[i] , 1 , s , 1);
if (a[i].h > 1) change(1 , a[i].h - 1 , -a[i].c , 1 , s , 1);
} memset(seg , 0 , sizeof seg);
memset(tag , 0 , sizeof tag);
for(register int i = n; i; i--)
{
g[i] = query(1 , a[i].h , 1 , s , 1) + a[i].p;
update(a[i].h , g[i] , 1 , s , 1);
if (a[i].h > 1) change(1 , a[i].h - 1 , -a[i].c , 1 , s , 1);
} for(register int i = 1; i <= n; i++) ans = max(ans , f[i] + g[i] - a[i].p);
printf("%lld" , ans);
}

JZOJ 4296. 有趣的有趣的家庭菜园的更多相关文章

  1. 【BZOJ4240】有趣的家庭菜园 树状数组+贪心

    [BZOJ4240]有趣的家庭菜园 Description 对家庭菜园有兴趣的JOI君每年在自家的田地中种植一种叫做IOI草的植物.JOI君的田地沿东西方向被划分为N个区域,由西到东标号为1~N.IO ...

  2. bzoj4240: 有趣的家庭菜园(树状数组+贪心思想)

    4240: 有趣的家庭菜园 题目:传送门 题解: 好题!%%% 一开始不知道在想什么鬼,感觉满足二分性?感觉可以维护一个先单调增再单调减的序列? 然后开始一顿瞎搞...一WA 看一波路牌...树状数组 ...

  3. [bzoj4240]有趣的家庭菜园_树状数组

    有趣的家庭菜园 题目链接:https://lydsy.com/JudgeOnline/problem.php?id=4240 数据范围:略. 题解: 第一步比较简单,只需要排序之后,每个数不是在左边就 ...

  4. bzoj4240有趣的家庭菜园(贪心+逆序对)

    对家庭菜园有兴趣的JOI君每年在自家的田地中种植一种叫做IOI草的植物.JOI君的田地沿东西方向被划分为N个区域,由西到东标号为1~N.IOI草一共有N株,每个区域种植着一株.在第i个区域种植的IOI ...

  5. 【bzoj4240】有趣的家庭菜园 贪心+树状数组

    题目描述 对家庭菜园有兴趣的JOI君每年在自家的田地中种植一种叫做IOI草的植物.JOI君的田地沿东西方向被划分为N个区域,由西到东标号为1~N.IOI草一共有N株,每个区域种植着一株.在第i个区域种 ...

  6. JOI2019 有趣的家庭菜园3

    问题描述 家庭菜园专家 JOI 先生在他的家庭菜园中种植了一种叫 Joy 草的植物.在他的菜园里,有 N 个花盆自东向西摆放,编号分别为 \(1, \ldots, N\).每个花盆中有一株 Joy 草 ...

  7. [bzoj4240] 有趣的家庭菜园

    还是膜网上题解QAQ 从低到高考虑,这样就不会影响后挪的草了. 每次把草贪心地挪到代价较小的一边.位置为i的草,花费为min( 1..i-1中更高的草的数目,i+1..n中更高的草的数目 ) 因为更小 ...

  8. 【bzoj4240】 有趣的家庭菜园 树状数组

    这一题最终要构造的序列显然是一个单峰序列 首先有一个结论:一个序列通过交换相邻的元素,进行排序,最少的交换次数为该序列的逆序对个数 (该结论很久之前打表意外发现的,没想到用上了.....) 考虑如何构 ...

  9. [BZOJ4240]有趣的家庭菜园(贪心+树状数组)

    最后数列一定是单峰的,问题就是最小化最后的位置序列的逆序对数. 从大到小加数,每次贪心看放左边和右边哪个产生的逆序对数更少,树状数组即可. 由于大数放哪对小数不产生影响,所以正确性显然. 注意相同数之 ...

  10. BZOJ4240 有趣的家庭菜园(贪心+树状数组)

    显然相当于使序列变成单峰.给原序列每个数按位置标号,则要求重排后的序列原标号的逆序对数最少.考虑将数从大到小放进新序列,那么贪心的考虑放在左边还是右边即可,因为更小的数一定会在其两侧,与它自身放在哪无 ...

随机推荐

  1. jquery &&、||

    $(function(){ $('.mainall').textbox({}); var r = 5; r=r==2&&r*8||r*3; alert(r); }); &&am ...

  2. 【大数据课程】高途课程实践-Day02:利用Hive SQL编写离线数仓实现可视化展示

    〇.概述 1.实现内容 使用Hive SQL编程,构造分层离线数仓 并可以通过Quick Bi进行展示 2.过程 (1)数据接⼊到ODS层 (2)进⾏ODS到DWD层数据开发 (3)进⾏ODS到DIM ...

  3. 过压保护芯片,高输入电压(OVP)

    PW2606是一种前端过电压和过电流保护装置.它实现了广泛的输入电压范围从2.5V到40V.过电压阈值可在外部编程或设置为内部默认设置.集成功率路径nFET开关的超低电阻确保了更好的性能电池充电系统应 ...

  4. ORM增删改查 django请求生命周期图 django路由层及反向解析

    目录 可视化界面之数据增删改查 1.建表 2.数据展示功能 3.数据添加功能 4.数据编辑功能 5.数据删除功能 django请求生命周期流程图 django路由层 1.路由匹配 2.转换器功能 pa ...

  5. redis(二)

    Redis简单使用 一. Redis的安装 Redis作为一款目前这个星球上性能最高的非关系型数据库之一. 拥有每秒近十万次的读写能力. 其实力只能用恐怖来形容. mac版本, brew: https ...

  6. python 学生管理系统 文件版 增删改查

    # 在程序开始之前完成数据的读取 # 存在着循环 # 循环的内容 # 将操作内容分解为函数 def sel_student(students_list): """ 查看所 ...

  7. Kali Win-KeX SL

    内容: 概述 先决条件 用法 开始 声音支持 多屏支持 停止 概述 无缝模式下的 Win-KeX 将在 Windows 桌面的屏幕顶部启动 Kali Linux 面板. 通过面板启动的应用程序将与 M ...

  8. [深度学习] tf.keras入门5-模型保存和载入

    目录 设置 基于checkpoints的模型保存 通过ModelCheckpoint模块来自动保存数据 手动保存权重 整个模型保存 总体代码 模型可以在训练中或者训练完成后保存.具体文档参考:http ...

  9. Python实现k-近邻算法案例学习

    一.介绍 你好,我是悦创. 博客首发:https://bornforthis.cn/column/Machine-learning/informal-essay/01.html 本文是由给私教学员 c ...

  10. 一文解决如何使用 C 语言判断质数(素数)[ 附解析与源码 ]

    前言 质数历来都是数学界的宠儿,是数学里神秘的谜团. 质数又和 C 语言有着不解之缘,本篇文章将讲解如何用 C 语言判断质数. 为了方便大家在读完此文章后使用文中程序,我会将判断质数的程序封装成函数, ...