题解 | #滑动窗口#

滑动窗口

https://ac.nowcoder.com/acm/problem/50528

用数组du作为单调队列,把对应a中的下标记录下来。l和r分别是数组du的左右界。以求区间最大为例,如果后来的元素更大,则前面比它小的元素就没机会成为最大了,直接去掉。若后来的元素更小,由于位序偏后,可能会成为某个区间的最大。当区间里的数多于k个,就把最前面的元素去掉。最终du对应a中的元素单调下降,最前面的元素a[du[l]]就是最大。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k;
ll a[1000010];
int du[1000010];//记录区间的第i个数在a中的下标 
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin >> n >> k;
    for(int i=0;i<n;i++)
        cin >> a[i];
    int l=0;
    int r=1;//左闭右开的区间
    //du是单调队列,存放在a中的下标 
    du[0]=0;//最开始的元素下标为0 
    if(k==1)    cout << a[0] << " ";//保证a的首元素会被输出
    for(int i=1;i<n;i++){//遍历a中元素 
        if(i-du[l]>=k )    l++;
        while(a[du[r-1]]>=a[i] && r>l)    r--;//注意左闭右开,du最后一位是r-1 
        du[r++]=i;
        if(i>=k-1)    cout << a[du[l]] << " ";
    } 
    cout << "\n";

    l=0;
    r=1;//左闭右开的区间
    //du是单调队列,存放在a中的下标 
    du[0]=0;//最开始的元素下标为0 
    if(k==1)    cout << a[0] << " ";
    for(int i=1;i<n;i++){//遍历a中元素 
        if(i-du[l]>=k )    l++;
        while(a[du[r-1]]<=a[i] && r>l)    r--;
        du[r++]=i;

        if(i>=k-1)    cout << a[du[l]] << " ";
    } 
    cout << "\n";
    return 0;
}
全部评论

相关推荐

09-01 11:31
门头沟学院 Java
buul:七牛云的吧,感觉想法是好的,但是大家没那么多时间弄他这个啊。。。不知道的还以为他是顶尖大厂呢还搞比赛抢hc,只能说应试者的痛苦考察方是无法理解的,他们只会想一出是一出
点赞 评论 收藏
分享
10-02 19:29
已编辑
浙江科技大学 运营
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务