• AtCoder


    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

    题意:给出一个序列,求每个子区间中中位数的中位数

    题解:

    首先如果A过牛客第一场提高组集训T1的神仙们肯定会知道前缀和+二分搞所有区间中位数的玩法

    大致操作如下:

    如果一个数比mid大,把它赋值为-1否则为1

    对这个数组来个前缀和

    此时如果某个区间的和为正数说明这个区间的中位数比mid小

    然后问题转化成如何求现在有多少个这个区间

    显然对前缀和求个顺序对就可以啦

    接着就是二分答案

    复杂度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
    ",mid);
    }
  • 相关阅读:
    NET Framework Library Source Code Now Available
    [笔记] C# 3.0 新特性[2]Understanding Extension Methods
    [笔记] C# 3.0 新特性[3]Understanding Object Initializers
    Tips: Save some typing when binding values to UI in WPF/Silverlight
    Test Driven Development
    How Default Parameter Works When It Comes Overload Method
    ASP.NET MVC 3 Refresh
    Avoid to use "IN", "NOT IN" in SQL statement, try to use "LEFT JOIN" instead.
    C# Rules
    Parameter sniffing may cause negative impact on performance
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/9750493.html
Copyright © 2020-2023  润新知