[POJ2823]Sliding Window(单调队列)

题目链接:

http://poj.org/problem?id=2823

题意:

给你一个序列a,要找到两个序列
a的下标为i,i+1,i+2, ….. i+k-1 当中的最小值为b[i];
c[i]就是最大值

题解:

单调队列,紫书中第八章的滑动窗口。。

优先队列也可做

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
#define MS(a) memset(a,0,sizeof(a))
#define MP make_pair
#define PB push_back
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//////////////////////////////////////////////////////////////////////////
const int maxn = 1e6+10;

struct node{
    int x,y;
}v[maxn];

int n,k;
int a[maxn],mi[maxn],mx[maxn];

void getmin(){
    int head=1,tail=0;
    for(int i=1; i<k; i++){
        while(head<=tail && a[i]<=v[tail].x) tail--; 
        tail++; v[tail].x=a[i],v[tail].y=i;
    }
    for(int i=k; i<=n; i++){
        while(head<=tail && a[i]<=v[tail].x) tail--; // 插入到第一个比a[i]小的下一个位置,并把无用的【不可能出现在答案里的值,如果后面的一个位置比这个位置的值小,那么肯定要小的】删除
        tail++; v[tail].x=a[i],v[tail].y=i;
        while(head<=tail && i-k+1>v[head].y) head++; // 删除队首,已经不再这个窗口里的元素
        mi[i-k+1] = v[head].x;
    }
}

void getmax(){
    int head=1,tail=0;
    for(int i=1; i<k; i++){
        while(head<=tail && a[i]>=v[tail].x) tail--;
        tail++; v[tail].x=a[i],v[tail].y=i;
    }
    for(int i=k; i<=n; i++){
        while(head<=tail && a[i]>=v[tail].x) tail--;
        tail++; v[tail].x=a[i],v[tail].y=i;
        while(head<=tail && i-k+1>v[head].y) head++;
        mx[i-k+1] = v[head].x;
    }
}

int main(){
    cin >> n >> k;
    for(int i=1; i<=n; i++)
        a[i] = read();
    getmin();
    getmax();

    cout << mi[1];
    for(int i=2; i<=(n-k+1); i++)
        cout << " " << mi[i];
    cout << endl;

    cout << mx[1];
    for(int i=2; i<=(n-k+1); i++)
        cout << " " << mx[i];
    cout << endl;

    return 0;
}

优先队列的写法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
#define MS(a) memset(a,0,sizeof(a))
#define MP make_pair
#define PB push_back
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//////////////////////////////////////////////////////////////////////////
const int maxn = 1e6+10;

int a[maxn],mi[maxn],mx[maxn];

struct node1{
    int i;
    bool operator<(const node1& rhs) const{
        return a[i]>a[rhs.i];
    }
};

struct node2{
    int i;
    bool operator<(const node2& rhs) const{
        return a[i]<a[rhs.i];
    }
};

priority_queue<node1> q1;
priority_queue<node2> q2;

int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n; i++)
        a[i] = read();
    for(int i=1; i<k; i++){
        q1.push(node1{i});
        q2.push(node2{i});
    }

    int cnt1=0,cnt2=0;

    for(int i=k; i<=n; i++){
        q1.push(node1{i});
        q2.push(node2{i});

        while(i-q1.top().i >= k) q1.pop();
        mi[cnt1++] = a[q1.top().i];

        while(i-q2.top().i >= k) q2.pop();
        mx[cnt2++] = a[q2.top().i];
    }

    for(int i=0; i<cnt1; i++){
        cout << mi[i];
        if(i==cnt1-1) cout << endl;
        else cout << " ";
    }

    for(int i=0; i<cnt2; i++){
        cout << mx[i];
        if(i==cnt2-1) cout << endl;
        else cout << " ";
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值