求助

P1886 滑动窗口 /【模板】单调队列

cstdios @ 2019-10-04 19:13:51

AC了一个点,请大佬们指点我一下:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>//头文件 
#define maxn 2000100 
using namespace std;
int q[maxn], a[maxn];//q为记录a数组的下标,a为读入的元素 
int n, k;//看题目 
void getmin() {//维护最小值 
  int head = 0, tail = 0;//头尾指针 

  for (int i = 1; i < k; i++) {
    while (head <= tail && a[q[tail]] >= a[i]) tail--;
    q[tail++] = i;
  }
  //假设数据是    1 2 3 4 5       head=0 tail=0 a:1 2 3 4 5 q:0
  //i=1  head=0 tail=1 a:1 2 3 4 5 q:0 1
  for (int i = k; i <= n; i++) {
    while (head <= tail && a[q[tail]] >= a[i]) tail--;
    q[++tail] = i;
    while (q[head] <= i - k) head++;
    printf("%d ", a[q[head]]);
  }
  // 然后开始 i=2 head =1 tail=1 a[1]>=a[2]条件不成立跳出,q[head=1]<=(i-k=0) q:0 1 2 输出 1
  //i=3  ....
}

void getmax() {
  int head = 0, tail = 0;
  for (int i = 1; i < k; i++) {
    while (head <= tail && a[q[tail]] <= a[i]) tail--;
    q[++tail] = i;
  }
  for (int i = k; i <= n; i++) {
    while (head <= tail && a[q[tail]] <= a[i]) tail--;
    q[++tail] = i;
    while (q[head] <= i - k) head++;
    printf("%d ", a[q[head]]);
  }
}

int main() {
  scanf("%d%d", &n, &k);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  getmin();
  printf("\n");
  getmax();
  printf("\n");
  return 0;
}

by Cwling @ 2019-10-04 19:22:42

推荐STL。STL大法好!


by Cwling @ 2019-10-04 19:27:36

你这个问题很明显

    while (head <= tail && a[q[tail]] >= a[i]) tail--;
    q[tail++] = i;
  }
  //假设数据是    1 2 3 4 5       head=0 tail=0 a:1 2 3 4 5 q:0
  //i=1  head=0 tail=1 a:1 2 3 4 5 q:0 1
  for (int i = k; i <= n; i++) {
    while (head <= tail && a[q[tail]] >= a[i]) tail--;
    q[++tail] = i;
    while (q[head] <= i - k) head++;
    printf("%d ", a[q[head]]);
  }

这一段问题就很大。 第一,我觉得应该只要一个for(1-n)就好了。 第二,你这个单调队列维护有很大问题,建议去看看别人的单调队列模板。对于单调队列我更推荐你去学一下STL双端队列的单调队列,挺好用的。如果你要的话我可以帮你写一下。


by cstdios @ 2019-10-04 19:34:38

@蔓翎 谢谢


|