zoukankan      html  css  js  c++  java
  • P1886 滑动窗口

    题意::::现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

    解法  1)单调队列   2)线段树(n * log n)

           单调队列分析::

               考虑最小值情况::

                   以该样例为例子说明::: 

                   8 3

                   1 3 -1 -3 5 3 6 7(在这里非常巧妙的就是用下标来维护窗口大小,保证均在合理范围内不越界)

                   q表示队列入队的为下标

                   1:队空 1 直接 入队 q={1}; 3 也直接入队 q={1,2};-1 则弹出前两项 q={3};

                   2:  -3 则弹出前一项 q={4}; 5 直接入队 q={4,5}; 3 则弹出前一项 q={4,6};同时 队头下次操作越界 所以pop q={6};

                   3:6 直接入队 q={6,7}; 7 也直接入队 q={6,7,8};同时 队头下次操作越界 所以pop q={7,8};

                   1):当队列非空且队尾指向的下标元素小于当前或等于当前值---->不断弹出队尾

                   2):下标入队尾

                   3):判断队头所指向的下标是否越界,是则 pop

               最大值情况同样考虑

       

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 const int maxn=1e6+5;
     4 using namespace std;
     5 
     6 int ma[maxn];
     7 int a[maxn],b[maxn];
     8 deque<int>q;
     9 int main()
    10 {
    11     int n,k;
    12     scanf("%d%d",&n,&k);
    13     for(int i=1;i<=n;i++){
    14         scanf("%d",&ma[i]);
    15     }
    16     //最小值
    17     for(int i=1;i<=n;i++)
    18     {
    19         while(!q.empty()&&ma[q.back()]>=ma[i]){
    20             q.pop_back();
    21         }
    22         q.push_back(i);
    23         a[i]=ma[q.front()];
    24         if(q.front()<=i-k+1&&i>=k){
    25             q.pop_front();
    26         }
    27     }
    28 
    29     while(!q.empty())
    30     {
    31         q.pop_back();
    32     }
    33     for(int i=1;i<=n;i++)
    34     {
    35         while(!q.empty()&&ma[q.back()]<=ma[i]){
    36             q.pop_back();
    37         }
    38         q.push_back(i);
    39         b[i]=ma[q.front()];
    40         if(q.front()<=i-k+1&&i>=k){
    41             q.pop_front();
    42         }
    43     }
    44     for(int i=k;i<=n;i++){
    45         printf("%d ",a[i]);
    46     }
    47     printf("
    ");
    48     for(int i=k;i<=n;i++){
    49         printf("%d ",b[i]);
    50     }
    51     return 0;
    52 }

                   线段树更容易理解就不解释了,贴代码 (AC 900+ms  时间看着很慌,数据好点估计会卡死)

          

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 const int MOD=1e9+7;
     4 using namespace std;
     5 const int maxn=1e6+5;
     6 
     7 int Min[4*maxn],a[maxn],Max[4*maxn];
     8 int ma[maxn],mb[maxn];
     9 
    10 void pushup(int rt)
    11 {
    12     Max[rt]=max(Max[2*rt],Max[2*rt+1]);
    13     Min[rt]=min(Min[2*rt],Min[2*rt+1]);
    14 }
    15 void build(int l,int r,int rt)
    16 {
    17     if(l==r){
    18         Max[rt]=a[l];
    19         Min[rt]=a[l];
    20         return ;
    21     }
    22     int mid=(l+r)>>1;
    23     build(l,mid,2*rt);
    24     build(mid+1,r,2*rt+1);
    25     pushup(rt);
    26 }
    27 
    28 int query1(int L,int R,int l,int r,int rt)
    29 {
    30     if(L<=l&&R>=r){
    31         return Max[rt];
    32     }
    33     int mid=(l+r)>>1;
    34     int ans=-1e9;
    35     if(L<=mid){
    36         ans=max(ans,query1(L,R,l,mid,2*rt));
    37     }
    38     if(R>mid){
    39         ans=max(ans,query1(L,R,mid+1,r,2*rt+1));
    40     }
    41     return ans;
    42 }
    43 int query2(int L,int R,int l,int r,int rt)
    44 {
    45     if(L<=l&&R>=r){
    46         return Min[rt];
    47     }
    48     int mid=(l+r)>>1;
    49     int ans=1e9;
    50     if(L<=mid){
    51         ans=min(ans,query2(L,R,l,mid,2*rt));
    52     }
    53     if(R>mid){
    54         ans=min(ans,query2(L,R,mid+1,r,2*rt+1));
    55     }
    56     return ans;
    57 }
    58 int main()
    59 {
    60     int n,m;
    61     scanf("%d%d",&n,&m);
    62     for(int i=1;i<=n;i++){
    63         scanf("%d",&a[i]);
    64     }
    65     build(1,n,1);
    66     for(int i=1;i<=n-m+1;i++)
    67     {
    68         ma[i]=query2(i,i+m-1,1,n,1);
    69         mb[i]=query1(i,i+m-1,1,n,1);
    70     }
    71     for(int i=1;i<=n-m+1;i++){
    72         printf("%d ",ma[i]);
    73     }
    74     printf("
    ");
    75     for(int i=1;i<=n-m+1;i++){
    76         printf("%d ",mb[i]);
    77     }
    78     return 0;
    79 }
    纵使单枪匹马,也要勇闯天涯
  • 相关阅读:
    vue中的Data为什么必须是一个函数
    单页面应用的优缺点
    数组去重
    mvvm框架
    前端计算精确度问题处理JS
    shell 修改json配置。
    ubuntu 两个文件夹合并
    fdisk、df与du的区别
    新买移动磁盘,使用前需要什么操作?
    Springboot+MybatisPlust+ControllerAdvice ;Mybatis_Plus多数据源,controller统一异常返回
  • 原文地址:https://www.cnblogs.com/sj-gank/p/11722821.html
Copyright © 2011-2022 走看看