zoukankan      html  css  js  c++  java
  • 集训第四周(高效算法设计)K题 (滑窗问题)

    UVA 11572 唯一的雪花

    题意:给你从1到n的数组,要求求得其中的最长连续不重复子序列,经典的滑窗问题,方法是维护一个窗口,设置左框和右框,然后不断的进行维护和更新

    方法一:

    #include"iostream"
    #include"set"
    #include"cstring"
    #include"cstdio"
    #include"algorithm"
    using namespace std;
    const int maxn=1000000+10;
    set<int>book;
    int a[maxn];
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            int n,t,sum=0,ans=0;
            cin>>n;
            book.clear();
            for(int i=0;i<n;i++)
            {
                cin>>a[i];
            }
            int r=0,l=0;
            for(;r<n;)
              {
                  while(!book.count(a[r])&&r<n)
                  {
                      book.insert(a[r]);
                      r++;
                  }
                  ans=max(ans,r-l);
                  book.erase(a[l]);
                  l++;
               }
            cout<<ans<<endl;
        }
        return 0;
    }
    

     方法二:

    #include"iostream"
    #include"set"
    #include"cstring"
    #include"cstdio"
    #include"algorithm"
    using namespace std;
    const int maxn=1000000+10;
    int pos[maxn];
    int a[maxn];
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            int n,t,sum=0,ans=0;
            cin>>n;
            memset(pos,-1,sizeof(pos));
            for(int i=0;i<n;i++)
            {
                cin>>a[i];
            }
            int r=0,l=0;
            a[n]=a[n-1];
            for(int i=0;i<=n;i++)
              {
                 if(pos[a[i]]>=l)
                 {
                     ans=max(ans,i-l);
                     l=pos[a[i]]+1;
                 }
                 pos[a[i]]=i;
              }
            cout<<ans<<endl;
        }
        return 0;
    }
    

     刘汝佳紫书上还提到过滑动窗口的最小值问题,其中使用到了单调队列,贴个地址去学习学习:

    http://m.blog.csdn.net/blog/lx417147512/24916441

    #include <stdio.h>
    #define MAX 1000001
    int n,k;
    int pre1,pre2,lst1,lst2,len_max,len_min; // 两个队列的头指针与尾指针,最大值的下标,最小值的下表
    int num[MAX],Increase[MAX],Decrease[MAX],Max[MAX],Min[MAX]; // Num存数据,递增与递减队列,最大值,最小值的数组。
    // 递减序列的压入操作
    void in_min(int i)
    {
    while( pre1<=lst1 && num[ Decrease[lst1] ]<num[i] ) //一直到寻找到比当前待插入值更大的位置,这是维护一个递减序列
    --lst1;
    Decrease[++lst1]=i;

    // 如果大于等于k个数,就需要向最大值数组赋值
    if( i>=k )
    {
    if(Decrease[pre1]<=i-k)
    pre1++;
    Max[len_max++]=num[ Decrease[pre1] ]; //当前滑动窗口的最大值即为递减序列的队头
    }
    }
    // 递增序列的压入操作
    void in_max(int i)
    {
    while( pre2<=lst2 && num[ Increase[lst2] ]>num[i] ) //一直到寻找到比当前待插入值更小的位置,这是维护一个递增序列
    --lst2;
    Increase[++lst2]=i;

    // 如果大于等于k个数,就需要向最小值数组赋值
    if( i>=k )
    {
    if(Increase[pre2]<=i-k)
    pre2++;
    Min[len_min++]=num[ Increase[pre2] ]; //当前滑动窗口的最小值即为递增序列的队头
    }
    }
    int main()
    {
    int i;
    while( ~scanf("%d%d",&n,&k) )
    {
    // 初始化
    pre1=pre2=len_max=len_min=0;
    lst1=lst2=-1;

    // 读入数据
    for(i=1;i<=n;++i)
    {
    scanf("%d",&num[i]);
    in_max(i);
    in_min(i);
    }

    // 输出数据
    for( i=0;i<len_min-1;++i )
    printf("%d ",Min[i]);
    printf("%d ",Min[len_min-1]);
    for( i=0;i<len_max-1;++i )
    printf("%d ",Max[i]);
    printf("%d ",Max[len_max-1]);
    }
    return 0;
    }

  • 相关阅读:
    搭建openstack系统初始化(2)
    Kvm虚拟化安装与虚拟机创建
    KVM-克隆和快照管理
    P4197 Peaks
    P4768 [NOI2018]归程
    #6145. 「2017 山东三轮集训 Day7」Easy 动态点分治
    P4178 Tree
    P4149 [IOI2011]Race
    P3806 【模板】点分治1
    P4724 【模板】三维凸包
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/4705309.html
Copyright © 2011-2022 走看看