翻译过来是:
问题陈述
给定的是一个排列P=(P_1,P_2,\ldots,P_N)P=(P1?,P2?,…,PN?)关于(1,2,\ldots,N)(1,2,…,N)和一个正整数K.
对于每个i=K,K+1,\ldots,Ni=K,K+1,…,N,找到以下内容。
- 这KK-第一个中最大的值i条款P.
限制
- 1次10^51≤K≤N≤5×105
- (P_1,P_2,\ldots,P_N)(P1?,P2?,…,PN?)是的排列(1,2,\ldots,N)(1,2,…,N).
- 输入中的所有值都是整数。
| 投入 | 输出 |
|---|---|
3 2 1 2 3 |
1 2 |
- 这(K=)(K=) 22-第一个中第二大值22条款PP, (P1,p2)=(1,2)(P1?,P2?)=(1,2),是11.
- 这(K=)(K=) 22-第一个中第二大值33条款PP, (P1,p2,P3)=(1,2,3)(P1?,P2?,P3?)=(1,2,3),是22.
投入
11 5 3 7 2 5 11 6 1 9 8 10 4 输出 2 3 3 5 6 7 7 这个题的意思是 第一次输出:从第一个到第k个数,排序之后第k大的数,第二次输出:从第一个数到第k+1个数,排序之后第k大的数,第三次输出第一个数到第k+2个数,排序之后第k大的数...知道最后输出第一个数到第n个数,排序之后第k大的数。
思路:如果按照平常的解法,加入一个数排一次序肯定会超时,所以这时候就用到stl里的优先队列来自动排好序,然后再找规律,第一次是从第一个开始到第k个数输出第k大的数,实际上就是从小到大排序之后的第一个数,再加入一个数之后第k大的数就是排序好的第2个数,为了方便操作,我们利用stl直接将排序之后的第一个数也就是队头删除之后再输出队头的数,刚好就是没删除之前的第二个数,然后插入第三个数的时候再删除队头,然后输出队头,就是全都没删除时的第三个数...以此类推。
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
int n,k,num,i;
priority_queue<int,vector<int>,greater<int> > a;//定义小根堆
int main(){scanf("%d %d",&n,&k);for(i=0;i<k;i++){scanf("%d",&num);a.push(num);}//先把前k个数输入a printf("%d\n",a.top());for(i=k;i<n;i++){scanf("%d",&num);a.push(num);//一个一个插入 a.pop();//插入之后删除最小的 printf("%d\n",a.top());//输出删除之后最大的 }return 0;
}