zoukankan      html  css  js  c++  java
  • 题解:中位数

    传送门

    首先考虑的是二叉搜索树,每次查找当前排名(i+1)/2的数。但是对于某些数据,其递归层数过多,会导致爆栈。

    那么显然可以用Treap或Splay。

    这里考虑线段树:

    由于线段树是一种平衡树,所以一定保证能跑出来。

    对于线段树,我们基于二叉搜索树的查找方法并介于线段树平衡的性质求解。

    对于线段树的每一个节点,我们记其大小为num,并记录其左边最大值和右边最小值。

    在插入时我们考虑存入一个有序数列,保证其根节点的元素单调递增。

    则其左边最大值和右边最小值分别为左儿子右端点和右儿子左端点。

    在插入时,若:

       当前值x=左最大=右最小,显然x=根节点。

    我们令根节点的num+1.

       当前值x>左最大,往右放;反之,往左放。

    在查询时:

      就相当于结合了二叉搜索树的找排名,和线段树的单点修改的样子。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define lson l,mid,rn<<1
    #define rson mid+1,r,rn<<1|1
    using namespace std;
    int n,a[100010],b[100010],size;
    struct cym{
        int num;
        int l_size,r_size;
    }tree[400010];
    void update(int rn)
    {
        tree[rn].num=tree[rn<<1].num+tree[rn<<1|1].num;
        tree[rn].l_size=tree[rn<<1].l_size;tree[rn].r_size=tree[rn<<1|1].r_size;
    }
    void build(int l,int r,int rn)
    {
        if(l==r)
        {
            tree[rn].l_size=tree[rn].r_size=b[l];
            return;
        }
        int mid=(l+r)>>1;
        build(lson);
        build(rson);
        update(rn);
    }
    void add(int x,int now)
    {
        if(tree[now].l_size==tree[now].r_size&&tree[now].l_size==x)
        {
            tree[now].num++;
            return;
        }
        if(x>tree[now<<1].r_size)
        add(x,now<<1|1);
        else
        add(x,now<<1);
        update(now);
    }
    int find(int l,int r,int rn,int rank)
    {
        if(l==r)
        return tree[rn].l_size;
        int mid=(l+r)>>1;
        int ans=0;
        if(rank<=tree[rn<<1].num)
        ans=find(lson,rank);
        else
        ans=find(rson,rank-tree[rn<<1].num);
        return ans;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        sort(b+1,b+1+n);
        size=unique(b+1,b+1+n)-(b+1);
        build(1,size,1);
        for(int i=1;i<=n;i++)
        {
            add(a[i],1);
            if(i&1)
            printf("%d
    ",find(1,size,1,(i+1)>>1));
        }
    }
  • 相关阅读:
    计算机工程-作图(可编辑)
    伪代码规范
    重启随机游走算法(RWR:Random Walk with Restart)
    二分图匹配——通俗易懂
    com.panie 项目开发随笔_爬虫初识(2017.2.7)
    Java获取随机数的3种方法
    我收藏的开源项目
    根据单击当前行的按钮时,获取 该行的其他列 的值
    js中的json对象和字符串之间的转化
    com.panie 项目开发随笔(NoF)_环境搭建(2016.12.29)
  • 原文地址:https://www.cnblogs.com/zzh666/p/9181274.html
Copyright © 2011-2022 走看看