Poj 2823 Sliding Window

题目描述http://poj.org/problem?id=2823

思路:

    求某个区间的最大与最小值,可以使用两个单调队列,由于需要在队列前删除元素和在队列后增加元素,所以考虑使用双端队列;

    在双端队列中记录元素的下标,另外,双端队列为单调队列,满足单调非递增或单调非递减,则队列第一个元素为区间最大或最小元素;

    这样可以找出区间中的最大与最小值。该算法为线性时间,时间复杂度为O(N)。

代码:

#include <iostream>
#include <deque>

#define MAX_N ( 100000 + 10 )

using namespace std;
int A[MAX_N];
deque<int> D( MAX_N );


void MaxOfSliding( int n, int k );
void MinOfSliding( int n, int k );

int main( )
{
    int n, k;

    while ( scanf( "%d %d", &n, &k ) != EOF )
    {
        for ( int i = 0; i < n; ++i )
            scanf( "%d", &A[i] );

        MinOfSliding( n, k );
        MaxOfSliding( n, k );
    }

    return 0;
}

void MaxOfSliding( int n, int k )
{
    int i;

    for ( i = 0; i < k - 1; ++i )
    {
        if ( !D.empty( ) && A[i] > D.back( ) )
            D.pop_back( );
        D.push_back( i );
    }

    for ( i = k - 1; i < n; ++i )
    {
        while ( !D.empty( ) && i - D.front( ) >= k )
            D.pop_front( );

        while ( !D.empty( ) && A[i] > D.back( ) )
            D.pop_back( );
        D.push_back( i );

        printf( "%d ",A[D.front( )] );
    }
    D.clear( );
    printf( "\n" );
}

void MinOfSliding( int n, int k )
{
    int i;

    for ( i = 0; i < k - 1; ++i )
    {
        if ( !D.empty( ) && A[i] < D.back( ) )
            D.pop_back( );
        D.push_back( i );
    }

    for ( i = k - 1; i < n; ++i )
    {
        while ( !D.empty( ) && i - D.front( ) >= k )
            D.pop_front( );

        while ( !D.empty( ) && A[i] < D.back( ) )
            D.pop_back( );
        D.push_back( i );

        printf( "%d ", A[D.front( )] );
    }
    D.clear( );
    printf( "\n" );
}

 

Poj 2823 Sliding Window

上一篇:Knockout: 实践CSS绑定和afterkeydown事件, 给未通过校验的输入框添加红色边框突出显示; 使用afterkeydown事件自动将输入转大写字母.


下一篇:Windows 10新体验(二):谈谈桌面的那点事