POJ2823(单调队列,二分出队列)

题意

给你n个数和一个区间的长度k,求从前往后每个[i,i+k-1] (1<=i<=n-k+1)区间的最大值和最小值。

题解

用单调队列搞一搞,然后。。。然后就超时了,学习了一下可以二分出队列,就去弄了一下二分(其实k不大的话二分也没啥用啊)。然后。。。然后就超时了。

好吧为什么G++就是会超时呢?用C++就过了。

代码

#include<cstdio>
#include <iostream>
#include<algorithm>
#include<string.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <queue>
using namespace std;

typedef long long ll;
const int N = 1e6+5;
int n, m;
int a[N];
int que[N]; //队列中a[i]的下标
int qu[N];
int Max[N];
int Min[N];
void getMax()
{
    int head=1,rear=0;
    for(int i=1;i <= n;i++)
    {
        if(rear>=head&&a[que[rear]]<=a[i]) {
            int r = rear, l = head;
            int mid;
            while(l < r)
            {
                mid = (l+r)>>1;
                if(a[que[mid]] <= a[i])
                    r = mid;
                else if(a[que[mid]] > a[i])
                    l = mid+1;
            }
            rear = l;
            que[rear] = i;
        }
        else
            que[++rear]=i; //插入到这个位置
        if(i>=m) {
            if(que[head]<i-m+1) {
                int r = rear, l = head;
                int mid;
                while(l < r)
                {
                    mid = (l+r)>>1;
                    if(que[mid] >= i-m+1)
                        r = mid;
                    else if(que[mid] < i-m+1)
                        l = mid+1;
                }
                head = l;
            }
            Max[i-m+1] = a[que[head]];
        }
    }
}
void getMin()
{
    int head = 1, rear = 0;
    for(int i = 1; i <= n; i++)
    {
        if(rear>=head&&a[que[rear]]>=a[i]) {
            int r = rear, l = head;
            int mid;
            while(l < r)
            {
                mid = (l+r)>>1;
                if(a[que[mid]] >= a[i])
                    r = mid;
                else if(a[que[mid]] < a[i])
                    l = mid+1;
            }
            rear = l;
            que[rear] = i;
        }
        else
            que[++rear] = i;
        if(i>=m) {
            if(que[head]<i-m+1) {
                int r = rear, l = head;
                int mid;
                while(l < r)
                {
                    mid = (l+r)>>1;
                    if(que[mid] >= i-m+1)
                        r = mid;
                    else if(que[mid] < i-m+1)
                        l = mid+1;
                }
                head = l;
            }
            Min[i-m+1] = a[que[head]];
        }
    }
}

int main()
{
    scanf("%d%d", &n, &m);

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

        getMin();
        getMax();
        for(int i = 1; i < n-m+1; i++)
            printf("%d ", Min[i]);
        printf("%d\n", Min[n-m+1]);

        for(int i = 1; i < n-m+1; i++)
            printf("%d ", Max[i]);
        printf("%d\n", Max[n-m+1]);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/QiHang_QiHang/article/details/81316674