链接:https://ac.nowcoder.com/acm/contest/9667/H
题目
有一个长度为n的数组,值为 a[i], 牛牛想找到数组中第 k 小的数。比如 1 2 2 3 4 6
中,第 3 小的数就是2.
牛牛觉得这个游戏太简单了,想加一点难度,现在牛牛有 m 个操作,每个操作有两种类型。
x 1
代表操作一,给数组中加一个元素 x 。(0 ≤ x ≤ 1e9)2
代表操作二,查询第 k 小的数。如果没有 k 个数就输出−1。
思路
一开始想着把所有数据放在multiset里,既能维持有序,取元素也不是很麻烦,结果T掉了。
后来翻AC代码的时候看到一个非常好玩的思路:
创建一个优先队列q,数值按照由大到小排序,然后将q的长度锁死在k。
这句话是什么意思呢?我们看一下样例:
5 4 3
1 2 3 4 5
当我们将数据存入优先队列q里时,我们先看一下q的长度:
若小于k则放入q中;若等于k,这时再放入元素x,需要看一下q.top()与该元素的大小关系。
比如样例中,放入前3个元素后,q.top()应该为3。当放入4时,我们需要看一下q.top()是否大于x。
3<4,所以无论后面的数如何,4一定不是第3小的那个。
如果我们向队列中再放入一个2,3>2,所以就当前而言,无论后面的数如何,3一定不是第3小的那个。
理解了上面这道题就简单了,看代码吧。
伊丽莎白!
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m,k;
int x,y;
priority_queue<int,vector<int>,less<int> >q;
cin>>n>>m>>k;
for(int i=0; i<n; i++)
{
cin>>x;
if(q.size()==k&&q.top()>x)
{
q.pop();
q.push(x);
}
else if(q.size()<k)
q.push(x);
}
while(m--)
{
cin>>x;
if(x==1)
{
cin>>y;
if(q.size()==k&&q.top()>y)
{
q.pop();
q.push(y);
}
else if(q.size()<k)
q.push(y);
}
else
{
if(q.size()<k)
cout<<"-1"<<endl;
else
cout<<q.top()<<endl;
}
}
}
《如果想恋爱就应该去努力争取而不是继续狗叫🐕🐕🐕》