AtCoder 4351 Median of Medians(二分+树状数组)
Posted lalalatianlalu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder 4351 Median of Medians(二分+树状数组)相关的知识,希望对你有一定的参考价值。
题意:给你列数,有一个中位数的定义,然后求出每一个区间的中位数,然后打印这些中位数的中位数
思路:没见过,真的学不来,看了聚聚们的博客以后,才学会。我们直接二分答案,我们有了答案以后,小于等于的mid的标记为1,其他的为-1,这样从一定程度上反应了区间大于和小于中位数的个数,对这个数组求前缀和,这样的话,我们变成了这样一个问题,我们如果找到一个正序数的一对数,这样这个区间的中位数就大于mid,这样的话,我们一直二分,会收敛到最后的中位数,因为二分是只需要判断能不能可行,不需要考虑答案是几,附一篇聚聚的博客(传送门)
(chaoxi)代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; inline LL read() { LL x=0,f=1;char ch=getchar(); while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } const int maxn=1e5+10; int a[maxn]; int n; int c[maxn*15]; int pre[maxn*15]; int lowbit(int x) { return x&-x; } void add(int x) { for(int i=x;i<=2*maxn;i+=lowbit(i))c[i]++; } LL query(int x) { LL res=0; for(int i=x;i>0;i-=lowbit(i))res+=c[i]; return res; } bool check(int x) { memset(c,0,sizeof(c)); pre[0]=0; for(int i=1;i<=n;i++)pre[i]=pre[i-1]+(a[i]>=x?1:-1); LL res=0; for(int i=0;i<=n;i++){ res+=query(pre[i]+maxn); add(pre[i]+maxn); } return res>=1LL*n*(n+1)/4; } int main() { n=read(); int L=0,R=0,ans=0; for(int i=1;i<=n;i++){ a[i]=read(); R=max(R,a[i]); } while(L<=R){ int mid=(L+R)>>1; if(check(mid)){ L=mid+1;ans=mid; } else{ R=mid-1; } } printf("%d ",ans); return 0; }
以上是关于AtCoder 4351 Median of Medians(二分+树状数组)的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Regular Contest 101 D - Median of Medians
AtCoder Grand Contest 020 C - Median Sum
AtCoder模型转化二分答案Median Pyramid Hard(AGC006)