单调队列模版80pts求调悬赏关注

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

Blue_Flower @ 2023-09-11 22:15:24

1很玄学,下载了测试数据之后本地跑了代码,与期望输出一致。。。

3 RE 不知所措。。。。。。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,k,h1=1,r1=1,h2=1,r2=1;
struct node{
    int id;
    ll data;
}w1[10000100],w2[10000100];   //懒得写循环队列,防越界多开了10倍的数组(虽然用不了那么大) 
//w1:升序  w2:降序 
ll read()   //快读 
{
    char x=getchar();
    ll res=0,f=1;
    if(x=='-') f=-1;
    while(x<'0'||x>'9') x=getchar();
    while(x>='0'&&x<='9') 
    {
        res=res*10+x-'0';
        x=getchar();
    }
    return res*f;
}

vector<ll> ans1,ans2;    //不知为何就是想用vector存答案 

int main()
{
    n=read();k=read();
    int tmp;
    w1[0].data=100000000000;
    for(int i=1;i<=n;i++)
    {
        tmp=read();
        //升序队列 
        while(i-k>=w1[h1].id) h1++;
        while(tmp<w1[r1-1].data&&r1>h1) r1--;
        w1[r1].data=tmp;w1[r1++].id=i;
        //降序队列 
        while(i-k>=w2[h2].id) h2++;
        while(tmp>w2[r2-1].data&&r2>h2) r2--;
        w2[r2].data=tmp;w2[r2++].id=i;
        //存答案 
        if(i>=k)
        {
            ans1.push_back(w1[h1].data);
            ans2.push_back(w2[h2].data);
        }
    }
    int len=ans1.size();
    for(int i=0;i<len;i++) printf("%lld ",ans1[i]);
    puts("");
    for(int i=0;i<len;i++) printf("%lld ",ans2[i]);
}

1 数据:

输入: 10 3 -94 21 24 73 38 77 11 73 9 -88 输出: -94 21 24 38 11 11 9 -88 24 73 73 77 77 77 73 73


by liuxy1234 @ 2023-09-11 22:19:10

访问w2的时候w2[h2]可能越界(w2为空,h2=1)


by Blue_Flower @ 2023-09-11 22:22:02

@liuxy1234 感谢dalao


by Blue_Flower @ 2023-09-11 22:28:32

@liuxy1234 不好意思能讲详细些吗,由于我太蒻了,想到的改进是这样的

   int tmp;
    w1[1].data=w2[1].data=read();
    w1[1].id=w2[1].id=1;
    for(int i=2;i<=n;i++)

然后就多WA了一个点


by liuxy1234 @ 2023-09-11 22:46:10

@liuhanming__nb 这两个下标从0开始设


by Blue_Flower @ 2023-09-11 22:49:30

@liuxy1234 就是队列头指针吗


by liuxy1234 @ 2023-09-11 23:07:22

@liuhanming__nb 实在是调不动了,一直90pts WA#1,我直接把我代码放这吧

#include <bits/stdc++.h>
#define int long long
using namespace std;

int a[1001000], q[1001000], M, n;

signed main()
{
    cin >> n >> M;
    for(int i = 1;i <= n;i++)scanf("%lld", &a[i]);
    q[1] = 1;
    int front = 1, rear = 1;
    for(int i = 1;i <= n;i++)
    {
        //入队尾 
        while(front <= rear && a[q[rear]] >= a[i])rear--;
        q[++rear] = i;
        //删队首
        while(front <= rear && q[front] <= i - M)front++;
        //取队首
        if(i > M - 1)cout << a[q[front]] << " ";
    }   
    puts("");
    q[1] = 1;
    front = 1, rear = 1;
    for(int i = 1;i <= n;i++)
    {
        //入队尾 
        while(front <= rear && a[q[rear]] <= a[i])rear--;
        q[++rear] = i;
        //删队首 
        while(front <= rear && q[front] <= i - M)front++;
        //取队首 
        if(i > M - 1)cout << a[q[front]] << " ";
    }
    return 0;
}

by liuxy1234 @ 2023-09-11 23:11:28

@liuhanming__nb wc调出来了,是你的read出问题了……


by liuxy1234 @ 2023-09-11 23:12:34

@liuxy1234 就是判断正负不一定进来第一个就是 -,建议把判断负号放进while不是数字里,像这样


inline int read()
{
    register int x = 0, f = 1;
    register char c = getchar();
    while(c < '0' || c > '9')
    {
        if(c == '-')f = -1;
        c = getchar();
    }
    while(c <= '9' && c >= '0')
    {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x * f;
}

by Blue_Flower @ 2023-09-12 21:23:50

@liuxy1234 昨天睡着了感谢dalao


by Blue_Flower @ 2023-09-12 21:34:15

@liuxy1234 我自己再调了一下过了,其实把判断队首元素过期的语句放在入队语句后就行了,快读的问题感谢,之前我一直写的都是错的

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,k,h1=0,r1=0,h2=0,r2=0;
struct node{
    int id;
    ll data;
}w1[10000100],w2[10000100];

inline ll read()
{
    int x = 0, f = 1;
    char c = getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c<='9'&&c>='0')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

vector<ll> ans1,ans2;

int main()
{
    n=read();k=read();
    int tmp;
    w1[0].data=10000000000;
    for(int i=1;i<=n;i++)
    {
        tmp=read();

        while(tmp<w1[r1-1].data&&r1>h1) r1--;
        w1[r1].data=tmp;w1[r1++].id=i;
        while(i-k>=w1[h1].id) h1++;

        while(tmp>w2[r2-1].data&&r2>h2) r2--;
        w2[r2].data=tmp;w2[r2++].id=i;
        while(i-k>=w2[h2].id) h2++;

        if(i>=k)
        {
            ans1.push_back(w1[h1].data);
            ans2.push_back(w2[h2].data);
        }
    }
    int len=ans1.size();
    for(int i=0;i<len;i++) printf("%lld ",ans1[i]);
    puts("");
    for(int i=0;i<len;i++) printf("%lld ",ans2[i]);
}

|