Hetao P1156 最大战力 题解 [ 绿 ][ 二分 ][ 最大子段和 ]
题解
形式化题意
给定两个数组 \(a[n]\) 和 \(b[n]\) ,需要在数组 \(b\) 中选择一个区间 \(b[l,r]\) ,替换掉区间 \(a[l,r]\) ,并且使替换后的 \(a'\) 数组的中位数最大。其中 $ 1 \le n \le 3*10^5 $ ,且 \(n\) 为奇数。
概述
本题思维难度较大,需要将中位数的浮动转化为 \(-1\) 或 \(1\) 的贡献,然后求贡献的最大子段和。
但是直接这样做,可能会得到并不是最大的的中位数,因为如果我们选择对一个静态的区间计算贡献,则可能在有多个最大贡献的子段和的情况下( 因为贡献的值只可能是 \(-1\) 或 \(1\) ),没有办法选择出 贡献与其他几个区间同样最大,但拥有这几个区间中最大的中位数的 区间。
因此,我们可以倒着来,在保证中位数合法的情况下,使中位数最大,而不是用贡献来直接确定最大中位数。这个过程需要二分中位数来实现。
总的时间复杂度为 \(O(n log n)\) 。
分析
二分
首先,要明确有奇数个元素的序列的中位数的求法。
1.把原数组排序,第 $ \frac{n+1}{2} $ 个元素就是中位数,时间 $ O(nlogn) $。
2.采用快速选择算法,即快速排序的简单应用,时间 $ O(n) $。
3.二分中位数,把 $\ge mid $ 的数标记为 \(1\) ( \(mid\) 表示中位数 ), $< mid $ 的数标记为 \(-1\)。当所有标记总和 $ > 0$ 时,说明当前的 $mid \le $ 真实的中位数;当所有标记总和 $ \le 0$ 时,表示当前的 $mid > $ 真实的中位数。( “当所有标记总和 $ \le 0$ 时,表示当前的 $mid > $ 真实的中位数”是因为中位数自身会被标记成 \(1\) ,且可能有多个中位数,所以选到中位数时总和一定 $ > 0$ 。 ),时间 $ O(nlogn)$ 。
可以注意到,对于 二分中位数 的做法,我们可以在二分时做一些手脚,对于当前二分的中位数 \(mid\) ,按前文所述来标记每个元素后,看看当前能否选出一个区间,能让这段区间替换原数组中的位置后使 替换后的中位数 变成合法的中位数,也就是说要让替换后的中位数最大 (因为最大中位数能选出来,那么比他小的中位数就一定能选出来)。
而判断一个中位数是否合法,就可以用前文中的标记总和的大小来判断。
这是二分答案题的基本套路。
最大子段和
有了二分,那么接下来就该实现选择区间,使中位数最大的模块了。
下文中,我们记 \(a[N]\) 为原数组,\(b[N]\) 为要替换的数组,\(c[N]\) 为替换的贡献的数组。
首先可以发现,标记的功能可以看做是一个一个贡献,比当前二分的数 \(mid\) 小的数贡献 \(-1\) ,其他贡献 \(1\) ,也就是说,这些贡献的总和就是 \(\ge mid\) 的数的数量 与 \(< mid\) 的数的数量 的差 。
而修改的区间则也需要这样标记,因为它可能被替换进原数组中。
有了这些标记,我们就可以计算出替换一个数的贡献 \(c[i]=b[i]-a[i]\)。
因为改了一个数,如果原本它 $ \ge mid$ ,而替换后 \(< mid\) ,则 \(a[i]=1,b[i]=-1\) ,所以 \(c[i]=-2\) ,而修改后少了一个 $ \ge mid$ 的数,多了个 \(< mid\) 的数,故 \(\ge mid\) 的数 变少了一个, \(< mid\) 的数 变多了一个,因此 \(\ge mid\) 的数的数量 与 \(< mid\) 的数的数量 的差 变小了 \(2\) ,所以修改贡献 \(-2\) 是正确的。
如果原本它 $ < mid$ ,而替换后 \(\ge mid\) ,则也是同理,\(c[i]=2\) 。
但如果修改前和修改后相对中位数 \(mid\) 的大小不变,则 \(c[i]=0\) ,对中位数没有任何影响。
求完 \(c\) 数组后,只要用 dp 来求 \(c\) 数组的最大子段和,就能求出对中位数的最大贡献了,此时 原本的标记的和 加上现在修改的最大子段和,就是现在标记的总和。
最大子段和的做法是对每一个 \(c[i]\) ,求出 \(c[1,i]\) 中的最小前缀和,再被 \(c[i]\) 的前缀和减去,更新当前最大子段和即可。并且开始时前缀和要设为 \(0\) ,最大子段和也要设为 \(0\) 。
注意,最大子段和在所有元素为负数时,会选择空区间,修改贡献总和为 \(0\) ,恰好对应本题中不替换任何元素的情况。
常见问题
Q1 : 修改一个数后,如果它的中位数变化了,那么之前的标记是否会失效?
A1 : 不会失效。
对于修改一个区间 \([l,r]\) ,可以把其看做 以任何顺序修改这些元素皆可,因此,只要从小到大修改这些元素,那么中位数就会不断变大,且中位数最大只可能是当前修改的这个元素,所以后面的数依旧比中位数要大,之前的标记不会失效。
因此,修改一个区间 \([l,r]\) ,无论什么顺序来修改最终的中位数都是固定的,所以代码中不用写这个功能。
Q2 : 能否在一个元素 \(=\) 中位数时把它标记成 \(0\) ?
A2: 不能。
hack: 1 , 2 , 3 , 3 , 3 , 3 , 3 , 4 , 5
___________________↑ ___________________
这时候有多个中位数,如果标记成 \(0\) ,那么相当于中位数全部被抵消,这时候即使选到了中位数,那么贡献总和也是 \(-1\) ,而正常情况下 贡献总和应该 $ \ge 1$ ,所以错误。
坑点
本题二分答案时 \(l\) 和 \(r\) 最大为 \(2*10^9\) ,此时它们相加求 \(mid\) 时会爆 int ,所以要开 long long 。
十年OI一场空,不开long long见祖宗
代码
#include<bits/stdc++.h>
using namespace std;
int n,a[300005],b[300005],c[300005];
int check(int mid)
{
int res=0;
for(int i=1;i<=n;i++)
{
if(a[i]>=mid)res++;
else res--;
//这里省略了标记 a[i] b[i] 的步骤,直接赋 c[i] 的值
if(a[i]>=mid && b[i]>=mid)c[i]=0;
else if(a[i]>=mid && b[i]<mid)c[i]=-2;
else if(a[i]<mid && b[i]>=mid)c[i]=2;
else c[i]=0;
}
int minres=0,sumn=0,maxres=0;
for(int i=1;i<=n;i++)
{
sumn+=c[i];
maxres=max(sumn-minres,maxres);
minres=min(minres,sumn);
}
return res+maxres;
}
int main()
{
freopen("yone.in","r",stdin);
freopen("yone.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i]>>b[i];
}
long long l=0,r=2e9+10,mid;
while(l<r)
{
mid=((l+r+1)>>1);//l+r加到最大时会爆int
if(check(mid)>=0)l=mid;
else r=mid-1;
}
cout<<l;
return 0;
}
Hetao P1156 最大战力 题解 [ 绿 ][ 二分 ][ 最大子段和 ]的更多相关文章
- CF912E Prime Gift题解(搜索+二分答案)
CF912E Prime Gift题解(搜索+二分答案) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1314956 洛谷题目链接 $ $ CF题目 ...
- 【题解】最大 M 子段和 Max Sum Plus Plus [Hdu1024] [51nod1052]
[题解]最大 M 子段和 Max Sum Plus Plus [Hdu1024] [51nod1052] 传送门:最大 \(M\) 子段和 \(Max\) \(Sum\) \(Plus\) \(Plu ...
- 【题解】 [HEOI2016]排序题解 (二分答案,线段树)
题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行 ...
- [NOIP2012提高]借教室 题解(二分答案+差分)
[NOIP2012提高&洛谷P1083]借教室 Description 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室 ...
- [CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)
[CodePlus 2017 11月赛&洛谷P4058]木材 Description 有 n棵树,初始时每棵树的高度为 Hi ,第 i棵树每月都会长高 Ai.现在有个木料长度总量为 S的订单, ...
- [NOIP2015提高&洛谷P2678]跳石头 题解(二分答案)
[NOIP2015提高&洛谷P2678]跳石头 Description 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之 ...
- [NOIP提高&洛谷P1024]一元三次方程求解 题解(二分答案)
[NOIP提高&洛谷P1024]一元三次方程求解 Description 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约 ...
- 【luogu P1156 垃圾陷阱】 题解
题目链接:https://www.luogu.org/problemnew/show/P1156 设\(dp[i][j]\)表示前i堆到达高度j时的所活最长时间 那么一旦到当前状态能到达满足的时间和高 ...
- [国家集训队2012]tree(陈立杰) 题解(二分+最小生成树)
tree 时间限制: 3 Sec 内存限制: 512 MB 题目描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. 输入 第一行V, ...
- [NOIP10.6模拟赛]1.merchant题解--思维+二分
题目链接: while(1)gugu(while(1)) 闲扯 考场上怕T2正解写挂其他两题没管只打了暴力,晚上发现这题思维挺妙的 同时想吐槽出题人似乎热衷卡常...我的巨大常数现在显露无疑QAQ 分 ...
随机推荐
- php-fpm常见错误
1. WARNING: Nothing matches the include pattern '/usr/local/php7/etc/php-fpm.d/*.conf' # cd /usr/loc ...
- 『玩转Streamlit』--可编辑表格
之前介绍过两个数据展示的组件,st.dataframe和st.table. 今天介绍的st.data_editor组件,除了展示数据的功能更加强大之外,还可以编辑数据. 1. 概要 st.data_e ...
- ELASTICSEARCH 读写性能优化
ELASTIC 写i性能优化 refresh translog flush refresh 优化 translog优化 flush 优化 读性能优化 shard 设置
- 《JavaScript 模式》读书笔记(4)— 函数3
这篇,我们来学习下自定义函数以及即时函数的内容. 四.自定义函数 函数可以动态定义,也可以分配给变量.如果创建了一个新函数,并且将其分配给保存了另外函数的同一个变量,那么就以一个新函数覆盖了旧函数.在 ...
- Simple FOC内置通信接口学习(二):电机命令接口
本文参(zhao)考(chao)至官方文档https://docs.simplefoc.com/docs_chinese/commander_interface Commander 接口 Comman ...
- 切换Docker本地目录
背景: df -h,发现docker默认的路径在/var/lib下,而且容量即将满掉. 对于欧拉系统来说,目录在/home,需要把docker目前的目录切换到/home下. 解决方法: 1. Dock ...
- NATS: 自定义服务 (Service)
使用 NATS 服务框架来创建服务会变得非常简单,基于 NATS 的服务框架,NAST 的客户端库可以更简单的构建.服务发现和监控服务.服务框架自动将所有的订阅归类到一个队列组中,提供构建基于层次化的 ...
- 【Go进阶】手写 Go websocket 库(一)|WebSocket 通信协议
前言 这里是白泽,我将利用一个系列,为你分享如何基于 websocket 协议的 rfc 文档,编写一个库的过程.并从0开始写一遍 gorilla/websocket 这个库,从中你可以学习到 web ...
- Dockerr安装Oracle以及使用DBeaver连接
拉取镜像 pull container-registry.oracle.com/database/free:latest 创建容器 说明一下我现在的最新版本是23 docker run -d --na ...
- Win11telnet服务怎么开启详细介绍
很多用户想知道在windows11电脑中要如何开启telnet服务,用户这时候是打开windows11电脑的设置,接着点击应用设置中的可选功能,然后点击更多windows功能就能看到telnet客户端 ...

