zoukankan      html  css  js  c++  java
  • Sliding Window

    poj2823 Sliding Window

        题目大意:给你一个n个数的序列,有一个长度固定的窗口,求出两个数列,分别是窗口从左滑到右,窗口内的最小值和最大值,分两行输出。

        注释:n<=$10^6$,内存<=64.

          想法:这内存是真恶心啊,正常的ST算法过不去,想到线段树,......咳咳,虽然这道题可以用单调队列和线段树没有什么障碍的A掉,但是今天我们仍然用ST维护RMQ来解决。首先,我们对内存有一定的限制,但是我们有一个极好的条件,那就是窗口的大小是固定的。所以,不难发现,我们所用到的f[i][j]数组只用到了最后一维,那么,我们想办法压维。压维最根本的是可否可行在于动态规划更新时是否有后效性。所以,我们就看一看。首先,我们显然知道,更新一个f的值所用到的,一定有一个是它自己,还有一个就是往后$2^{j-1}$所代表的值,不难发现,这两个下表都不小于i。所以,我们在从左向右松弛1-n时,所用到的下标都是没有被这一轮更新的,也就是说,是没有后效性的,故此,我们压维是可以的。所以,这道题就A掉了。

        在此,我们有一个东西,就是log数组是不需要占用一个数组的内存的,我们发现,我们窗口固定时,log所提取的数也是固定的,那么我们就可以在预处理时顺便将log的值附好,即可。

        最后,附上丑陋的代码... ...

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #define N 1000010
     5 using namespace std;
     6 int a[N];
     7 int f[N],g[N];
     8 int main()
     9 {
    10     int n,len;
    11     int maxlog;
    12     while(~scanf("%d%d",&n,&len))
    13     {
    14         // memset(f,0,sizeof(f));
    15         // memset(g,0,sizeof(g));
    16         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    17         for(int i=1;i<=n;i++)//初始化 
    18         {
    19             f[i]=a[i];
    20             g[i]=a[i];
    21         }
    22         maxlog=0;//这点贼重要,我们发现如果len==1,maxlog没有值??! 
    23         for(int i=1;(1<<i)<=len;i++)
    24         {
    25             maxlog=i;
    26             for(int j=1;j+(1<<i)-1<=n;j++)
    27             {
    28                 f[j]=max(f[j],f[j+(1<<(i-1))]);
    29                 g[j]=min(g[j],g[j+(1<<(i-1))]);
    30             }
    31         }
    32         // cout<<"maxlog="<<maxlog<<endl;
    33         // for(int i=1;i+(1<<maxlog)-1<=n;i++)
    34         // {
    35             // cout<<"f["<<i<<"]="<<f[i]<<endl;
    36         // }
    37         for(int i=1;i<=n-len+1;i++)
    38         {
    39             printf("%d ",min(g[i],g[i+len-(1<<maxlog)]));
    40         }
    41         printf("
    ");//别忘记分行 
    42         for(int i=1;i<=n-len+1;i++)
    43         {
    44             printf("%d ",max(f[i],f[i+len-(1<<maxlog)]));
    45         }
    46         printf("
    ");
    47     }
    48 }

        小结:RMQ的点还有很多,还是那句话,倍增的想法的重要性要超过这个算法本身。

          错误:1.maxlog的初始化,极其重要。

             2.在初始化时,注意端点的位置。

  • 相关阅读:
    命令模式(Command Pattern)
    外观模式(Facade Pattern)
    Hash函数的安全性
    单向散列函数
    装饰者模式(Decorator Pattern)
    尝试设计LFSR加密器,并用CAP4验证随机性
    对称密码-流密码
    组合模式(Composite Pattern)
    桥接模式(Bridge Pattern)
    适配器模式(Adapter Pattern)
  • 原文地址:https://www.cnblogs.com/ShuraK/p/8282520.html
Copyright © 2011-2022 走看看