scu 3139単調キュー

3780 ワード

リンク:http://acm.scu.edu.cn/soj/problem.action?id=3139 単調キューの古典的な応用.标题:長さnのスライド窓があり、スライド窓を右にまっすぐ移動し、このスライド窓の最大値の最小値がどれだけあるかを決定します.単調キュー:両端キューとも呼ばれます.最大値の保存を例にとります.キュー内の要素は単調で減らない.キューヘッダには最大値が格納され、要素をキューに追加するたびに、キューの最後からこの要素よりも小さなポップアップが表示され、最後にこの要素がキューに追加されます.キューの要素がスライド窓の外にあるかどうかを判断するたびに、いるとポップアップします.キュー内の各要素は、元の配列のインデックスと独自の値を保存できます.スライド窓内にあるかどうかを判断するのに便利です.もちろんインデックスだけを保存して、元の配列で探せばいいのです.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 1000009
typedef struct
{
    int index;
    int num;
}node;
node que1[M],que2[M]; //1     ,2     
int ans1[M],ans2[M];
int main()
{
    //freopen("ans.txt","r",stdin);
    int n,k;
    while(scanf("%d %d",&n,&k) == 2)
    {
        int head1 = 0,tail1 = 0;
        int head2 = 0,tail2 = 0;
        for(int i = 0;i < n;i++)
        {
            int a;
            scanf("%d",&a);
            while(head1 != tail1 && que1[tail1-1].num > a) tail1--; //              ,      
            que1[tail1++] = {i,a};
            if(que1[head1].index <= i-k) head1++;
            while(head2 != tail2 && que2[tail2-1].num < a) tail2--;
            que2[tail2++] = {i,a};
            if(que2[head2].index <= i-k) head2++;
            if(i >= k-1)
            {
                ans1[i-k+1] = que1[head1].num;
                ans2[i-k+1] = que2[head2].num;
            }
        }
        for(int i = 0;i <= n-k;i++) printf("%d%c",ans1[i],i==n-k ? '
'
:' '); for(int i = 0;i <= n-k;i++) printf("%d%c",ans2[i],i==n-k ? '
'
:' '); } return 0; }