• Evanyou Blog 彩带


      题目传送门

      理解题意:给定一个数列和窗口范围k,求依次向右移动窗口时每次窗口内的最大和最小值。

      没什么思维难度,一边扫过去,用两个数组maxx和minn记录每个窗口内的最大最小值,移动过程中用两个变量L和R记录窗口的左右端点,然后判断滑动窗口时最大最小值是否被移出窗口,进入窗口的值是否大于当前最大值或小于当前最小值,做完后L++,R++,用while循环控制轻松水过这题。当然,如果数据比较极端故意卡时就可能没这么轻松了。(不过我估计也不太可能会有什么题目出这么可怕的数据)

      下面是AC代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #define N 1000010
    #define ll long long
    using namespace std;
    const ll inf=9999999999;
    ll n,k,a[N],maxx[N],minn[N];
    void ready()
    {
      cin>>n>>k;
      for(int i=1;i<=n;i++)
        cin>>a[i];
    }
    void work()
    {
      ll l=1,r=k,cnt=0;
      ll mx=-inf,mn=inf;
      for(int i=l;i<=r;i++){
        mx=max(mx,a[i]);
        mn=min(mn,a[i]);
      }
      maxx[++cnt]=mx;
      minn[cnt]=mn;
      l++;r++;
      while(r<=n){
        if(a[l-1]==mx){
          mx=-inf;
          for(int i=l;i<=r;i++)
        mx=max(mx,a[i]);}
        if(a[l-1]==mn){
          mn=inf;
          for(int i=l;i<=r;i++)
        mn=min(mn,a[i]);}
        if(a[r]>mx)mx=a[r];
        if(a[r]<mn)mn=a[r];
        maxx[++cnt]=mx;
        minn[cnt]=mn;
        l++;r++;
      }
      for(int i=1;i<=cnt;i++)
        cout<<minn[i]<<" ";
      cout<<endl;
      for(int i=1;i<=cnt;i++)
        cout<<maxx[i]<<" ";
    }
    int main()
    {
      //freopen("water.in","r",stdin);
      std::ios::sync_with_stdio(false);
      ready();work();return 0;
    }

    当然,滑动窗口在其他很多算法中都会用到,所以很有必要掌握好。

  • 相关阅读:
    for循环实战性能优化
    MySQL group_concat 介绍
    MySQL 取分组后每组的最新记录
    MySQL查询top N记录
    常用SQL之日期格式化和查询重复数据
    Java 8 ThreadLocal 源码解析
    避免创建不必要的对象
    IntelliJ IDEA 设置忽略SVN文件和文件夹
    scrapy+selenium+chromedriver解析动态渲染页面
    java读取excel或者csv时日期格式数据处理
  • 原文地址:https://www.cnblogs.com/cytus/p/7786955.html
Copyright © 2020-2023  润新知