24. AtCoder-Median of Medians
题目链接:Median of Medians
经典的二分做法。如果一个数有机会成为中位数,那么比它小的数不超过 个,比它大的数也不超过 个。所以我们可以这样验证一个数是否有机会成为答案:将原序列中小于这个数的都变成 ,其他的数变成 ,如果某个子区间的和是非负数,说明这个子区间原来的中位数小于等于我们检测的数。我们可以用树状数组 的求出所有这种子区间的数量 。由于子区间的总数量是 ,如果 ,说明这个数有机会成为答案,接下来检查更大的值,否则说明这个数太大必不可能成为答案,往小的值去找。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 2e5 + 5;
const ll mod = 1e9 + 7;
ll bit[maxn];
int lowbit(int x) {
return x & -x;
}
void add(int x, int k) {
for (int i = x; i < maxn; i += lowbit(i))
bit[i] += k;
}
ll sum(int x) {
ll ret = 0;
for (int i = x; i > 0; i -= lowbit(i))
ret += bit[i];
return ret;
}
ll a[maxn], b[maxn];
ll n;
ll t[maxn];
bool check(ll x) {
memset(bit, 0, sizeof(bit));
for (int i = 1; i <= n; ++i) {
t[i] = a[i] >= x ? 1 : -1;
}
ll ans = 0;
add(n, 1);
for (int i = 1; i <= n; ++i) {
t[i] += t[i - 1];
ans += sum(t[i] + n);
add(t[i] + n, 1);
}
return (ans >= n * (n + 1) / 4);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
for (int i = 1; i <= n; ++i)
b[i] = a[i];
sort(b + 1, b + n + 1);
int tot = unique(b + 1, b + n + 1) - b - 1;
int l = 1, r = tot, ans;
while (l <= r) {
int mid = (l + r) >> 1;
if (check(b[mid]))
l = mid + 1, ans = b[mid];
else
r = mid - 1;
}
cout << ans << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!