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); }