可恶啊,Easy居然让yzh抢了一步

这是一道有趣的题目

歪解时间

这里先借一下被GM公开处刑的超时代码,方便后面正解的引入

#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[200005],aa[200005];
bool check(int num){int a_0=0,a_1=0;          //后文解释两个变量的作用for(int i=1;i<=n*2-1;i++){aa[i]=a[i];if(aa[i]>=num){a_1++;}else{a_0++;}}for(int i=1;i<n;i++){if(a_1<=1){return 0;}if(a_0<=1){return 1;}a_0=a_1=0;for(int j=1;j<=2*n-1-2*i;j++){int x=aa[j],y=aa[j+1],z=aa[j+2];if(x>y){swap(x,y);}if(y>z){swap(y,z);}if(x>y){swap(x,y);}aa[j]=y;if(aa[j]>=num){a_1++;}else{a_0++;}}}
}
int main(){scanf("%d",&n);for(int i=1;i<=n*2-1;i++){scanf("%d",&a[i]);}int l=1,r=n*2-1;while(l<r){int mid=(l+r+1)/2;if(check(mid)){l=mid;}else{r=mid-1;}} printf("%d",l);return 0;
}

二分思路很简单,如果当前二分的这个数是大于等于实际答案的,则改变左端点,反之,改变右端点

这里浅浅解释一下a_0a_1的作用

a_1统计当前数列中大于等于mid的数量,a_0统计当前数列中小于mid的数量

如果a_1<=1,说明数列中的数几乎都是小于mid的,最终得出来的结果肯定是小于mid的,a_0<=1同理

明显T到飞起

由于二分本身是一个 O ( log ⁡ n ) O(\log n) O(logn) 的算法,那么check里面只能考虑 O ( n ) O(n) O(n)

正在苦思冥想之时,我的目光注射到了a_0a_1

正解时间

首先要清楚一个母庸质疑的结论:三个数 a , a , b a,a,b a,a,b 的中位数是 a a a

基于此,我们开始头脑风暴

我们可以按照处理a_0a_1的思路,将原序列转化成一个01串, 0 0 0 表示该数字小于mid, 1 1 1 表示该数字大于等于mid

将原序列转化成01串后,可以将该01串拆成如下的基本结构:000001111101010

为了方便描述,我们分别取名为ABC

我们讨论一下如下两种情况

  1. AB相邻

如上图,这两个串的中间是一条完美的分水岭,两个串会不断向上伸展,而不向左右伸展

证明很简单

设左边串的右端点为 r r r,右边串的左端点为 l l l,整个串是 S S S 串,转化后的串是 s s s 串

∀ i ( i ≠ l , i ≠ r ) , S i = s i \forall\ i(i\ne l,i\ne r),S_i=s_i ∀ i(i​=l,i​=r),Si​=si​

如上的结论应该是显然的,因为 S i − 1 = S i = S i + 1 S_{i-1}=S_i=S_{i+1} Si−1​=Si​=Si+1​

对于 S l S_l Sl​ ,因为 S l − 1 = S l S_{l-1}=S_l Sl−1​=Sl​ ,根据我们一开始所推得的结论,不难得出 S l = s l S_l=s_l Sl​=sl​

对于 S r S_r Sr​ ,因为 S r + 1 = S r S_{r+1}=S_r Sr+1​=Sr​ ,得出 S r = s r S_r=s_r Sr​=sr​

综上, ∀ i , S i = s i \forall\ i,S_i=s_i ∀ i,Si​=si​

那么,这第一个结论也就得证了

  1. A(或B)与C相邻

这里考虑AC相邻

我们发现:A串会一点一点的向C串延伸,直至“吃掉”整个C

证明:

设左边串的右端点为 r r r,右边串的左端点为 l l l,整个串是 S S S 串,转化后的串是 s s s 串

∀ i ( i ≤ r ) , S i = s i \forall\ i(i\le r),S_i=s_i ∀ i(i≤r),Si​=si​

∀ i ( i > l ) , ∴ S i − 1 = S i + 1 ∵ s i = S i − 1 \forall\ i(i>l),\therefore\ S_{i-1}=S_{i+1}\ \because\ s_i=S_{i-1} ∀ i(i>l),∴ Si−1​=Si+1​ ∵ si​=Si−1​

对于 i = l i=l i=l ,因为 S i S_i Si​ 与 S i + 1 S_{i+1} Si+1​ 中各有一个 0 0 0 和 1 1 1 ,则 s i s_i si​ 的取值决定于 S i − 1 S_{i-1} Si−1​,所以 s i = S i − 1 s_i=S_{i-1} si​=Si−1​

综上, ∀ i ( i ≤ r ) , S i = s i , ∀ j ( j ≥ l ) , S j = s j − 1 \forall\ i(i\le r),S_i=s_i,\forall\ j(j\ge l),S_j=s_{j-1} ∀ i(i≤r),Si​=si​,∀ j(j≥l),Sj​=sj−1​

得出了这两个结论后,我们可以进行进一步推理

为了后文推理方便,这里定义一个概念:串到点的距离

对于一个串 [ l , r ] [\ l,r\ ] [ l,r ](左端点下标为 l l l,右端点下标为 r r r) ,这个串到下标为 a a a 的点的距离为 min ⁡ ( a − l , a − r ) \min(a-l,a-r) min(a−l,a−r)

特殊的,如果 l ≤ a ≤ r l\le a\le r l≤a≤r ,则距离为 0 0 0

很显然,当 S n S_n Sn​ 属于A串或属于B串时,就可以确定最终结果了(因为只有A串和B串是永恒不变的)

那么, S n S_n Sn​ 初始时会有两种情况

  1. S n S_n Sn​ 属于A串或B

此时我们已经能确定答案了,且 S n S_n Sn​ 到该串(A串或B串)的距离为 0 0 0

  1. S n S_n Sn​ 属于C

因为 S n S_n Sn​ 属于C串,所以,C串左右的A串和B串可以通过C串一步步占领 S n S_n Sn​,显然,距离 S n S_n Sn​ 近的一个串会占领 S n S_n Sn​

综上,我们不难发现:如果某一个A串距离 S n S_n Sn​ 的距离比任何一个B串距离 S n S_n Sn​ 的距离都要小,则最终 S n S_n Sn​ 属于A串,结果为 0 0 0;如果某一个B串距离 S n S_n Sn​ 的距离比任何一个A串距离 S n S_n Sn​ 的距离都要小,则最终 S i S_i Si​ 属于B串,结果为 1 1 1

所以,只需要求离 S n S_n Sn​ 最近的A串到 S n S_n Sn​ 的距离和离 S n S_n Sn​ 最近的B串到 S n S_n Sn​ 的距离即可

当然,原序列或许会有只有C串的情况,特判即可

代码如下:

#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[200005],aa[200005];
bool check(int num){for(int i=1;i<=n+n-1;i++){if(a[i]>=num){aa[i]=1;}else{aa[i]=0;}}int a_0=2147483647,a_1=2147483647;for(int i=n;i>=1;i--){           //求离 S_n 最近的A串到 S_n 的距离if(aa[i]==0&&aa[i-1]==0){a_0=n-i;break;}}for(int i=n;i<=n+n-1;i++){if(aa[i]==0&&aa[i+1]==0){a_0=min(a_0,i-n);break;}}for(int i=n;i>=1;i--){          //求离 S_n 最近的B串到 S_n 的距离if(aa[i]==1&&aa[i-1]==1){a_1=n-i;break;}}for(int i=n;i<=n+n-1;i++){if(aa[i]==1&&aa[i+1]==1){a_1=min(a_1,i-n);break;}}if(a_0==2147483647&&a_1==2147483647){            //只有C串if(aa[n]==0){if(n%2==0){return 1;}return 0;}if(n%2==0){return 0;}return 1;}if(a_0==2147483647){           //没有A串return 1;}if(a_1==2147483647){          //没有B串return 0;}if(a_0>a_1){return 1;}return 0;
}
int main(){scanf("%d",&n);aa[0]=-1,aa[n+n]=-1;for(int i=1;i<=n*2-1;i++){scanf("%d",&a[i]);}int l=1,r=n*2-1;while(l<r){int mid=(l+r+1)/2;if(check(mid)){l=mid;}else{r=mid-1;}} printf("%d",l);return 0;
}

Median Pyramid Hard题解相关推荐

  1. 奖牌分配/Median Pyramid Hard

    题目背景 有一个环形的围墙,围墙上有一些塔,每个塔中有一个守卫. 题目描述 现在要发给每个守卫一些奖章,第i个守卫需要P[i]个奖章.每个守卫自己的奖章必须都是不同种类的,而且相邻的两个守卫得到的奖章 ...

  2. PAT甲级1029 Median:[C++题解]贪心、二路归并

    文章目录 题目分析 题目来源 题目分析 来源:acwing 分析: 如果直接排序,时间复杂度是O(nlogn),n=2∗105O(nlogn),\ n=2*10^5O(nlogn), n=2∗105会 ...

  3. 【Python CheckiO 题解】Median

    CheckiO 是面向初学者和高级程序员的编码游戏,使用 Python 和 JavaScript 解决棘手的挑战和有趣的任务,从而提高你的编码技能,本博客主要记录自己用 Python 在闯关时的做题思 ...

  4. CF676B Pyramid of Glasses 题解

    description: solution: i d e a 1 idea1 idea1: 暴力,每一秒枚举情况 时间复杂度 O ( n 2 t ) O(n^2t) O(n2t),但是本题不会超时 i ...

  5. 2019牛客全国多校训练三 题解

    A Gragh Games Unsolved. B Crazy Binary String 题解:水题,子序列只要统计0和1数量,取最小值然后乘2就是答案: 对于子串:先记录0和1 前缀和的差值,然后 ...

  6. Codeforces Round #703 (Div. 2)(A ~ F)超高质量题解【每日亿题2 / 19】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 A. Shifting Stacks B - Eastern Exhibition C1 - G ...

  7. HDU 3282 Running Median 动态中位数,可惜数据范围太小

    Running Median Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...

  8. 【最新合集】PAT甲级最优题解(题解+解析+代码)

    以下每道题均是笔者多方对比后, 思考整理得到的最优代码,欢迎交流! 共同成长哇.可以和博主比拼一下谁刷的更快~ 欢迎收藏.欢迎来玩儿 PAT题解目录 题号 标题 题解 分类 使用算法 1001 A+B ...

  9. 【19行代码AC,简洁】1029 Median (25 分)

    立志用最少的代码做最高效的表达 PAT甲级最优题解-->传送门 Given an increasing sequence S of N integers, the median is the n ...

最新文章

  1. Unity3d连接SQL Server数据库出现SocketException: 使用了与请求的协议不兼容的地址错误...
  2. Redis的优势和特点
  3. 如何惹毛一名开发者?
  4. java写文件方法之比较
  5. HTML、CSS、JS都有哪些区别
  6. 高等数学上-赵立军-北京大学出版社-题解-练习5.8
  7. 按窗口文件php代码,在Windows命令行窗口中输入并运行PHP代码片段(不需要php文件)的方法...
  8. 超清晰的 DNS 原理入门指南 (资源)
  9. paip.提升用户体验-----c++ 宏的使用...替换从在的地张儿复制过来的代码.
  10. glide源码中包含了那种设计模式_Glide源码解读(一)
  11. Firemonkey Control的TabStop处理
  12. 渥太华计算机读研的好学校,加拿大硕士留学:渥太华最好的大学硕士项目
  13. blastall参数详解
  14. 计算机组成原理——计算机系统概述
  15. Mendix助力工业数字化 :“智能制造百家讲堂”问题回顾
  16. 毕业设计-基于深度学习的图像隐写分析
  17. 希望计算机专业同学都知道这些宝藏博主
  18. P2P通信中的NAT/FW穿越
  19. OpenCV 视频地址和图片地址注意事项
  20. 中国再领跑:成功发射全球首颗6G试验卫星?

热门文章

  1. 丘成桐大学生数学竞赛数学物理
  2. 清除FTP登录的用户名密码
  3. ttkefu微信二维码对话链接如何生成?
  4. [渝粤教育] 山东大学 2021秋中国武术文化(艺术英语) 参考 资料
  5. 孩子学习机器人编程究竟有没有用?
  6. python爬虫笔记(学习T)
  7. win 10家庭版升专业版报错:0xC004F069在运行Microsoft Windows非核心版本的计算机上……
  8. 5G白皮书(5G服务路线图 2022)
  9. 圆柱体积怎么算立方公式_圆柱体积怎么算 求圆柱体积的公式
  10. 【FlutterFlame 游戏 - 壹】开启新世界的大门