2016春季练习——优先队列的一个神奇用法

来源:POJ2823

这一题对于时间还是挺紧的,所以这个方法很巧妙。

这是我Tle

#include <iostream>

#include <cstdio>

#include <map>

#include <queue>

#include <stack>

using namespace std;

const int MAXN=1000010;

int a[MAXN];

int mina[MAXN],maxn[MAXN];

priority_queue<int,vector<int>,greater<int> >p1;

priority_queue<int,vector<int>,less<int> >p2;

stack<int>s;

int main(){

int n,k,i;

scanf("%d%d",&n,&k);

for(i=0;i<n;i++){

scanf("%d",a+i);

}

for(i=0;i<k;i++)

{

p1.push(a[i]);

p2.push(a[i]);

}

for(i=0;i<n-k+1;i++){

maxn[i]=p2.top();

mina[i]=p1.top();

while(p2.top()!=a[i]){

s.push(p2.top());

p2.pop();

}

p2.pop();

while(!s.empty()){

p2.push(s.top());

s.pop();

}

while(p1.top()!=a[i]){

s.push(p1.top());

p1.pop();

}

p1.pop();

while(!s.empty()){

p1.push(s.top());

s.pop();

}

p1.push(a[i+k]);

p2.push(a[i+k]);

}

for(i=0;i<n-k;i++)

{

printf("%d ",mina[i]);

}

printf("%d\n",mina[i]);

for(i=0;i<n-k;i++)

{

printf("%d ",maxn[i]);

}

printf("%d\n",maxn[i]);

return 0;

}

中间用一个栈存了弹出来的东西,然后重新弹出第一个,在重新压进去,当时想出来觉的能节约不少时间,其实是太天真了。两个优先队列来回弹,复杂度比在区间刷一遍都高!!!真是天真了。

这个问题对于优先队列的用法真是大开眼界,就是用优先队列来存指针(数组下标),维护的值是a[]中的值,我在代码里面说。当然,这个时候就要自己写cmp了,不用用greaterless水水。还有就是,注意那个数组大小要数清楚了,因为这个还RE了一发。

我在代码注释里面说好了。

#include <iostream>

#include <cstdio>

#include <queue>

#include <vector>

using namespace std;

const int MAXN=10000100;

int a[MAXN];

int aa[MAXN],bb[MAXN];

struct cmp1{

bool operator()(const int x,const int y){

return a[x]>a[y];

}

};

struct cmp2{

bool operator()(const int x,const int y){

return a[x]<a[y];

}

};

//上面两个就是,维护a数组的排序的指针的两个优先队列

priority_queue<int ,vector<int> ,cmp1>p1;

priority_queue<int ,vector<int> ,cmp2>p2;

 

int main(){

int n,k;

scanf("%d%d",&n,&k);

int i;

for(i=0;i<n;i++)

scanf("%d",&a[i]);

for(i=0;i<k;i++)

{//前i个,这个时候a数组没有排序,但是我已经知道具体的顺序了

p1.push(i);

p2.push(i);

}

int cnt1,cnt2;

cnt1=cnt2=0;

aa[cnt1++]=a[p1.top()];

bb[cnt2++]=a[p2.top()];

//这两个数组显然是表示最后的结果,先将前K的最大最小放进去,容易理解

for(i=k;i<n;i++){

p1.push(i);

p2.push(i);

//压进去后面的,好理解

//下面就是日了本鶸的两步啊

/*i-p1.pop()就是说,我没有必要考虑一定要让之前的那个元素出去,只要它不是最大或者最小值,我都没必要弹出,保留在里面没有关系,如果i-p1.pop()是>=k了,就说明这个解不在里面了,我直接去掉好了,再找一个最小值,非常精彩的做法

*/

while(i-p1.top()>=k)

p1.pop();

aa[cnt1++]=a[p1.top()];

while(i-p2.top()>=k)

p2.pop();

bb[cnt2++]=a[p2.top()];

}

//下面废话,群巨都会,不说了

for(i=0;i<n-k;i++)

{

printf("%d ",aa[i]);

}

printf("%d\n",aa[i]);

for(i=0;i<n-k;i++)

{

printf("%d ",bb[i]);

}

printf("%d\n",bb[i]);

return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值