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 分 ...
随机推荐
- redis6.0安装与使用
[Linux] 源码安装: 下载安装 Cd /usr/local/src/ wget https://download.redis.io/releases/redis-6.0.9.tar.gz $ t ...
- Golang常见问题汇总
在开始使用golang的时候,经常会遇到各种问题,总结在此 1.unrecognized import path "golang.org/x/.. golang 在 github 上建立了一 ...
- uni-app小程序项目使用iconfont字体图标
前情 uni-app是我比较喜欢的跨平台框架,它能开发小程序/H5/APP(安卓/iOS),重要的是对前端开发友好,自带的IDE让开发体验非常棒,公司项目就是主推uni-app. 为什么要这么做? 借 ...
- dfm格式初解之TTreeView
TTreeView 的 Items.NodeData 值解析: Items.NodeData = { 0302000000200000000000000000000000FFFFFFFFFFFFFFF ...
- mybatis-plus逻辑删除不生效的解决办法
我们在使用mybatis-plus时,一般设备逻辑删除是非常简单的,基本上在yaml等配置文件中做一下配置.然后在字段上注解@TableLogic就可以了.有不清楚的,可以参考https://www. ...
- File and Code template
/** * @author muzhi.zhong * @author <a href="mailto:muzhi.z@xxx.cn">muzhi.z</a> ...
- 尝试 vmware 16.0.0 过虚拟化 过xf虚拟机检测
前言 最新想在vmware虚拟机上玩xf,网上找了不少教程,于是打算自己尝试下. 如果可以修改成功的话,其价值嘛不可估量. 环境 vmware版本是16.0.0,已安装VMware Tools vmw ...
- 配置Ubuntu上的NFS
$sudo apt-get install nfs-kernel-server nfs-common 配置 $sudo vim /etc/exports#添加#/home/pi/project/roo ...
- 【源码】ByteToMessageDecoder对比自定义实现
前言 在上一篇随笔中,我们探讨了如何实现一套自定义通信协议,其中涉及到的粘包和拆包处理最初是完全自定义实现的,后来则改为了继承 ByteToMessageDecoder 来简化处理. 本篇将重点讨论这 ...
- MS Webview2 拦截 interact/intercept
https://docs.microsoft.com/en-us/microsoft-edge/webview2/how-to/webresourcerequested?tabs=dotnet 自定义 ...

