[AtCoder ARC101D/ABC107D] Median of Medians


題目鏈接

題意:給n個數,求出所有子區間的中位數,組成另外一個序列,求出它的中位數

這里的中位數的定義是:將當前區間排序后,設區間長度為m,則中位數為第m/2+1個數

做法:二分+前綴和+樹狀數組維護

極其妙的一個做法。

效率$O(nlognlogA)$這里的A指的是原序列中的最大值

二分一下最后的中位數,然后將原序列中大於當前二分出來的值標為1,小於的標為-1,處理出前綴和。

那么只要一段區間的和大於0,那么這段區間的中位數就一定大於等於當前二分出來的值。

所以問題就變成了,求出當前這個序列的順序對個數(兩個數是順序對,當且僅當$ai<aj,i<j$),用類似於逆序對的方法求

那么做法就很顯然了,用樹狀數組維護一下,單次check的效率就是$O(nlogn)$

要注意的一個點是,這里的樹狀數組不能有負數,所以得加個1e5強制轉正(因為是下標)

至於check的$true$和$false$,如果最后算出來的順序對個數大於$n*(n-1)/4$那么就是$true$(一共有$n*(n-1)/2$個區間,然后因為我們要求的中位數在中間,所以要再除一次2)

 

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define inf 1<<30
#define il inline 
#define in1(a) read(a)
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
il void readl(ll &x){
    x=0;ll f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    x*=f;
}
il void read(int &x){
    x=0;int f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    x*=f;
}
using namespace std;
/*===================Header Template=====================*/
#define N 100010
#define lowbit(x) x&-x
int c[N*10];
int n,a[N],s[N*10];
void add(int x){
    for(int i=x;i<=2*N;i+=lowbit(i))c[i]++;
}
ll query(int x){
    ll sum=0;
    for(int i=x;i>0;i-=lowbit(i))sum+=c[i];
    return sum;
}
bool check(int x){
    for(int i=1;i<=2*N;i++)c[i]=0;
    s[0]=0;
    for(int i=1;i<=n;i++)
        s[i]=s[i-1]+(a[i]>=x?1:-1);
    ll sum=0;
    for(int i=0;i<=n;i++){
        sum+=query(s[i]+N);
        add(s[i]+N);
    }
    return sum>=1ll*n*(n+1)/4;
}
int main(){
    in1(n);
    int l=0,r=0;
    for(int i=1;i<=n;i++){
        in1(a[i]);
        r=max(r,a[i]);
    }
    int ans=0;
    while(l<=r){
        int mid=(l+r)>>1;
        if(check(mid))l=mid+1;
        else r=mid-1;
    }
    printf("%d\n",r);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM