把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end
现实中并没有|

high_skyy

园龄:4个月粉丝:3关注:30 随笔 - 19  文章 - 6  评论 - 2  阅读 - 429

2025-02-09 12:19阅读: 1评论: 0推荐: 0

[AGC006D] Median Pyramid Hard 题目分析

[AGC006D] Median Pyramid Hard 题目分析

评价

一道非常好的思维题目!!!

分析

注意到:从三个数选一个中位数。

似乎没有什么好的方法,但是每一层的迭代有一种相似方法。

我们假设一个答案。

将大于等于答案的标记为 1,其他的为 0

三——一个非常重要的数,我们要考虑以下:

全是0:000 -> 0
一个1:001 -> 0
两个1:101 -> 1
三个1:111 -> 1

我们发现得到的答案取决于数量(0 多还是 1 多)。

那我们怎么确定他能一直走到尾呢?

注意到:

 ???        ----->     00?
x00zy                 x00zy

也就是说,两个连续的在一起,能够使得上面也一样(但是要看边界)。

注意到要是中间有连续的(即最靠近中间的一段 0 或者 1)说明顶尖就是大于等于数字。

我们发现这样具有单调性,于是乎可以考虑二分答案解决。

然后我们就很好的解决了该问题。

总时间复杂度 O(nlogn).

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stdlib.h>
#include <cstring>
#include <vector>
#define N 100005
using namespace std;
int a[N << 2],n,b[N << 2];
bool check(int x) {
	for (int i = 1;i <= 2 * n - 1;i ++) b[i] = (a[i] >= x);
	for (int dis = 0;dis < n - 1;dis ++) {
		if (b[n + dis] == b[n + dis + 1]) return b[n + dis];
		if (b[n - dis] == b[n - dis - 1]) return b[n - dis];
	}
	return b[1];
}
signed main(){
	cin >> n;
	for (int i = 1;i <= 2 * n - 1;i ++) cin >> a[i];
	int l = 1,r = 2 * n - 1,res = r;
	while(l <= r) {
		int mid = l + r >> 1;
		if (check(mid)) res = mid,l = mid + 1;
		else r = mid - 1;
	}
	cout << res;
	return 0;
} 

拓展:如何去掉 log

我们可以通过二分算法得到线性算法,这是一个好方法。

我们发现我们得到一个对的值那么我们只需要扫一遍就可以了。那么这个对的值就是 1,改变成 2 只需要改变原本 1 的位置,判断也只需要往中间判断是否有连续的 0 即可。

本文作者:high-sky

本文链接:https://www.cnblogs.com/high-sky/p/18705960

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   high_skyy  阅读(1)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起