刷题记录(NC214362 第k小,NC50940 Running Median)

NC214362 第k小

题目链接

关键点:

1、观察题目,要求每次输出第k小的数,我们如果对这个数组进行排序,那么比第k小的数(x)还大的数,是没有可能在未来成为第k小的数,分析如下:

如果此时插入一个比x大的数,那么第k小的数还为x

如果此时插入一个比x小的数,那么第k小的数只能为x前面的数(比x还小)

2、因此每次要求求第k小的数时,我们将比k大的数给扔掉,不再继续判断,这种既可以排序,又可以扔掉大的数的为大顶堆,那么可以直接用优先队列

完整代码

# include <iostream>
# include <queue>
# include <cstdio>
using namespace std;
int n, m, k;
priority_queue<int>q;
int main()
{
    cin>>n>>m>>k;
    for (int i=1; i<=n; i++)
    {
        int x;
        cin>>x;
        q.push(x);
    }
    for (int i=1; i<=m; i++)
    {
        int x;
        cin>>x;
//         cout<<"top = "<<q.top()<<endl;
        if (x == 2)
        {
            if (q.size()<k)
                cout<<"-1"<<endl;
            else
            {
                while (q.size()!=k)
                    q.pop();
                cout<<q.top()<<endl;
            }
        }
        else
        {
            int y;
            cin>>y;
            q.push(y);
        }
    }
    
    
    return 0;
}

NC50940 Running Median

题目链接

关键点: 

1、题目要求每次输入为奇数个时,输出中位数大小,我们用一个大顶堆存比当前中位数小的元素,一个小顶堆存比当前中位数大的元素,并且保持这两个顶堆元素个数相同

2、原因:每次求出奇数个数的中位数(x),接下来再插入元素,之后的中位数在该中位数的左右进行偏移,如果比x小,那么从小于x中的最大值中为中位数,比x大,那么从大于x中的最小值里去找

3、维护两个堆,如果两堆元素个数相同,中位数为各自top值的平均数,如果哪一方多一个,那么就为那一方的top值,如果当将一个元素插入一个堆中时,该堆个数多于另一个堆的1个时,将多的堆的top元素加入另一个堆里

完整代码

# include <iostream>
# include <cstdio>
# include <queue>
using namespace std;
int t, pos;
int a[10000+10];
int main()
{
    cin>>t;
    while (t--)
    {
        int xu, n;
        pos = 0;
        priority_queue<int>d;
        priority_queue<int, vector<int>, greater<int> >x;
        cin>>xu>>n;
        int f, mid;
        cin>>f;
        x.push(f);
        a[++pos] = f;
        mid = f;
        for (int i=2; i<=n; i++)
        {
            cin>>f;
//             cout<<"mid = "<<mid<<endl;
            if (f<mid)
            {
                d.push(f);
                if (d.size()-x.size() > 1)
                {
                    x.push(d.top());
                    d.pop();
                }
            }
            else
            {
                x.push(f);
                if (x.size() - d.size() > 1)
                {
                    d.push(x.top());
                    x.pop();
                }
            }
//             cout<<x.size()<<" "<<d.size()<<endl;
            int ds = d.size(), xs = x.size();
            if (ds-xs == 1)
                mid = d.top();
            else if (xs-ds == 1)
                mid = x.top();
            else
                mid = (x.top()+d.top())/2;
            if (i%2)
                a[++pos] = mid;
        }
        cout<<xu<<" "<<pos<<endl;
        for (int i=1; i<=pos; i++)
        {
            if (i%10)
                cout<<a[i]<<" ";
            else
                cout<<a[i]<<endl;
        }
        cout<<endl;
    }
    
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值