AtCoder - 4351 Median of Medians(二分+線段樹求順序對)

D - Median of Medians

Time limit : 2sec / Memory limit : 1024MB

Score : 700 points
Problem Statement

We will define the median of a sequence b of length M, as follows:

    Let b' be the sequence obtained by sorting b in non-decreasing order. Then, the value of the (M⁄2+1)-th element of b' is the median of b. Here, ⁄ is integer division, rounding down.

For example, the median of (10,30,20) is 20; the median of (10,30,20,40) is 30; the median of (10,10,10,20,30) is 10.

Snuke comes up with the following problem.

You are given a sequence a of length N. For each pair (l,r) (1≤l≤r≤N), let ml,r be the median of the contiguous subsequence (al,al+1,…,ar) of a. We will list ml,r for all pairs (l,r) to create a new sequence m. Find the median of m.
Constraints

    1≤N≤105
    ai is an integer.
    1≤ai≤109

Input

Input is given from Standard Input in the following format:

N
a1 a2 … aN

Output

Print the median of m.
Sample Input 1
Copy

3
10 30 20

Sample Output 1
Copy

30

The median of each contiguous subsequence of a is as follows:

    The median of (10) is 10.
    The median of (30) is 30.
    The median of (20) is 20.
    The median of (10,30) is 30.
    The median of (30,20) is 30.
    The median of (10,30,20) is 20.

Thus, m=(10,30,20,30,30,20) and the median of m is 30.
Sample Input 2
Copy

1
10

Sample Output 2
Copy

10

Sample Input 3
Copy

10
5 9 5 9 8 9 3 5 4 3

Sample Output 3
Copy

8

題意:給出一個序列,求每一個子區間中中位數的中位數node

 

題解:c++

首先若是A過牛客第一場提升組集訓T1的神仙們確定會知道前綴和+二分搞全部區間中位數的玩法數組

大體操做以下:ui

若是一個數比mid大,把它賦值爲-1不然爲1spa

對這個數組來個前綴和code

此時若是某個區間的和爲正數說明這個區間的中位數比mid小orm

而後問題轉化成如何求如今有多少個這個區間blog

顯然對前綴和求個順序對就能夠啦element

接着就是二分答案it

複雜度nlognlogai

 

代碼以下:

#include<bits/stdc++.h>
#define lson root<<1
#define rson root<<1|1
using namespace std; int n; int a[200010]; int sum[200010]; struct node { int l,r,sum; }tr[1600080]; int push_up(int root) { tr[root].sum=tr[lson].sum+tr[rson].sum; } int build(int root,int l,int r) { if(l==r) { tr[root].sum=0; tr[root].l=l; tr[root].r=r; return 0; } tr[root].l=l; tr[root].r=r; int mid=(l+r)>>1; build(lson,l,mid); build(rson,mid+1,r); push_up(root); } int update(int root,int pos) { if(pos==tr[root].l&&pos==tr[root].r) { tr[root].sum++; return 0; } int mid=(tr[root].l+tr[root].r)>>1; if(pos<=mid) { update(lson,pos); } else { update(rson,pos); } push_up(root); } int query(int root,int l,int r) { if(l>r) return 0; if(l<=tr[root].l&&tr[root].r<=r) return tr[root].sum; int mid=(tr[root].l+tr[root].r)>>1; if(r<=mid) { return query(lson,l,r); } else { if(l>mid) { return query(rson,l,r); } else { return query(lson,l,mid)+query(rson,mid+1,r); } } } int check(int x) { long long ans=0; memset(sum,0,sizeof(sum)); for(int i=1;i<=n;i++) { sum[i]=sum[i-1]+((a[i]<=x)?1:-1); } for(int i=0;i<=n;i++) { sum[i]+=n+1; } build(1,1,200010); for(int i=0;i<=n;i++) { ans+=query(1,1,sum[i]-1); update(1,sum[i]); } return ans>=1ll*n*(n+1)/4+1; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } int l=1,r=1e9,mid; while(l<=r) { mid=(l+r)>>1; if(check(mid)) { r=mid; } else { l=mid+1; } if(r-l<=1) { mid=check(l)?l:r; break; } } printf("%d\n",mid); }
相關文章
相關標籤/搜索