放牧代码和思想
专注自然语言处理、机器学习算法
    愛しさ 優しさ すべて投げ出してもいい

POJ 2823 Sliding Window​ 题解《挑战程序设计竞赛》

目录

挑战程序设计竞赛第二版.jpg

POJ 2823 Sliding Window 

滑动最大小最值:给定长度为n的数组,求长度为k的滑动窗口内的最大最小值。

4.4常用技巧精选(二) 

双端队列 

没什么好说的,把书上的模板简单拓展一下就行了:

#include <iostream>

#define MAX_N 1000000 + 16
// 输入
int n, k;
int a[MAX_N];

int b[2][MAX_N];// 最小值与最大值
int deq[2][MAX_N];  // 单增单减两个双端队列

void solve()
{
    int s[2], t[2];  // 双端队列的头部和末尾
    memset(s, 0, sizeof(s)), memset(t, 0, sizeof(t));

    for (int i = 0; i < n; i++)
    {
        // 在双端队列的末尾加入i
        while (s[0] < t[0] && a[deq[0][t[0] - 1]] >= a[i])
            t[0]--;
        deq[0][t[0]++] = i;
        while (s[1] < t[1] && a[deq[1][t[1] - 1]] <= a[i])
            t[1]--;
        deq[1][t[1]++] = i;

        if (i - k + 1 >= 0)
        {
            b[0][i - k + 1] = a[deq[0][s[0]]];
            b[1][i - k + 1] = a[deq[1][s[1]]];

            if (deq[0][s[0]] == i - k + 1)
            {
                // 从双端队列的头部删除元素
                s[0]++;
            }
            if (deq[1][s[1]] == i - k + 1)
            {
                // 从双端队列的头部删除元素
                s[1]++;
            }
        }
    }

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

int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; ++i)
    {
        scanf("%d", a + i);
    }
    solve();
#ifndef ONLINE_JUDGE
    fclose(stdin);
#endif
    return 0;
}
16478401 hankcs 2823 Accepted 10972K 5469MS C++ 1393B 2017-01-15 10:24:47

知识共享许可协议 知识共享署名-非商业性使用-相同方式共享码农场 » POJ 2823 Sliding Window​ 题解《挑战程序设计竞赛》

评论 欢迎留言

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

我的作品

HanLP自然语言处理包《自然语言处理入门》