poj 2823 单调队列

//单调队列求滑动窗口的最大值和最小值
//题意是给一个n个数,在每k个数区间内
//求最大值和最小值

//单调队列:队列中的元素是单调的。
//求最小值的时候:进队的时候将队尾部大于当前要进的元素全部出队
//这样,队列的头部就是最小值
//反之,求最大值也是一样

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 1e6 + 8;
int a[maxn];
int n,k;
int vmi[maxn];
int vmx[maxn];
int deq[maxn];

void input(){
    for (int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
}

void getmin(){
    int head=0,tail=0;
    int cnt = 0;
    for (int i=1;i<=n;i++){
        while(tail > head && a[deq[tail-1]]>=a[i])
            tail--;
        deq[tail++] = i;

        if (i-k+1>=0){
            vmi[i-k+1] = a[deq[head]];
            if (i - k + 1 == deq[head]) // 这里的意思是最小值是第x个区间的最左边的值,这个值不在求的
                                        //下一个区间内
                head++;
        }
    }
}

void getmax(){
    int head = 0,tail = 0;
    int cnt = 0;
    for (int i=1;i<=n;i++){
        while (tail > head && a[deq[tail-1]] <= a[i])
            tail--;
        deq[tail++] = i;

        if (i-k+1>=0){
            vmx[i-k+1] = a[deq[head]];
            if (i-k+1 == deq[head]){ // 这里的意思是最小值是第x个区间的最左边的值,这个值不在求的
                                     //下一个区间内
                head ++ ;
            }
        }
    }
}

void print(int a[]){
    for (int i=1;i<=n-k+1;i++){
        printf("%d%c",a[i],(i==n-k+1)?'\n':' ');
    }
}

void solve(){
    getmax();
    getmin();
    print(vmi);
    print(vmx);
}

int main(){
    //freopen("1.txt","r",stdin);
    while(scanf("%d %d",&n,&k)!=EOF){
        input();
        solve();
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-28 13:36:03

poj 2823 单调队列的相关文章

Sliding Window POJ - 2823 单调队列模板题

Sliding Window POJ - 2823 单调队列模板题 题意 给出一个数列 并且给出一个数m 问每个连续的m中的最小\最大值是多少,并输出 思路 使用单调队列来写,拿最小值来举例 要求区间最小值 就是维护一个单调递增的序列 对于样例 8 3 1 3 -1 -3 5 3 6 7 我们先模拟一遍 1.队列为空 1 进队 队列:1 2.3>队尾元素 3 进队 队列: 1 3 3.-1小于队尾元素,一直从尾部出队知道找到比-1小的元素或者队列为空 队列:-1 当队列中元素大于m的时候从队头删

poj 2823 单调队列裸题

两个队列分别维持最大和最小 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; struct node { int mi,ma; }num[1000010]; int sax[1000010],sin[1000010]; int ida[1000010],idi[1000010]; int main() { int n,m,i,j,k,a; while(~scanf(&

poj 2823 单调队列 deque写法

Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 46435   Accepted: 13417 Case Time Limit: 5000MS Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left

POJ 3017 单调队列dp

Cut the Sequence Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8764   Accepted: 2576 Description Given an integer sequence { an } of length N, you are to cut the sequence into several parts every one of which is a consecutive subseque

POJ 2838 单调队列

Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 55309   Accepted: 15911 Case Time Limit: 5000MS Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left

poj 3017 单调队列

只能说是代码美如画.(当然我是指内在逻辑不是我的代码风格,队长看到要理解哈,啊哈哈哈哈哈哈哈哈) 正常思路咯,f[i]=f[j]+max(a[j+1],a[j+2]....a[i]),枚举j,显然硬来会超时,所以需要有一个单调队列来时时把最大值尽快弄出来并且需要一些剪枝: 剪枝条件有两个,一个是和不能超过m,一个是显然f[i]是个非严格递增序列,根据这两个条件剪枝: 则建立单调队列,每当插入新的i时将前面先把和小于等于m的条件做好,然后对于j<i,如果a[j]<a[i]就可以把j丢弃,那么显然

poj2823Sliding Window——单调队列

题目:http://poj.org/problem?id=2823 单调队列模板. 代码如下: #include<iostream> #include<cstdio> using namespace std; int n,k,a[1000005],mx[1000005],mn[1000005]; int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) { scanf("%d&

[ACM] poj 2823 Sliding Window(单调队列)

Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 36212   Accepted: 10723 Case Time Limit: 5000MS Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left

POJ 2823 Sliding Window(单调队列)

[题目链接] http://poj.org/problem?id=2823 [题目大意] 给出一个数列,问每k个数总最小值和最大值分别是多少 [题解] 单调队列顺序维护需求,时间节点超过k的点就出队 我们维护两次单调队列,用xor的小trick可以降低码量. [代码] #include <cstdio> #include <algorithm> using namespace std; const int MAX_N=1000010; int n,k; int a[MAX_N],b