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 Prefix Median(AGC012)

AtCoder Grand Contest 020 C - Median Sum

AtCoder模型转化二分答案Median Pyramid Hard(AGC006)

[Leetcode] Median of Two Sorted Arrays

LeetCode--median-of-two-sorted-arrays