UVA 11572 Unique Snowflakes(滑窗|双指针)

这篇博客介绍了如何使用滑窗和双指针算法解决UVA 11572 Unique Snowflakes问题。文章详细阐述了题意,即在给定的序列中找到最长的连续子序列,确保其中没有重复元素。通过移动右指针直至遇到重复元素,然后移动左指针来维持序列的独特性,利用集合来判断是否存在相同元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UVA 11572 Unique Snowflakes

题意

一个长度为n的序列A,找到一个尽量长的连续子序列,并且该序列中没有相同元素

解决

  1. 以区间来思考这个问题,让右指针不断增加,增加到一个不能增加(冲突)的位置
  2. 当无法延伸右指针,也就是说A[right]在A[left,right-1]这段出现过,此时增大左指针
  3. 我们增加左指针的时候,可以保证A[left+1,right-1]这一段仍是可行解,所以不必减小右指针
  4. 判断是否存在相同元素:**利用set

双指针示范

/*
     1   2   3   2   1      left    right   right-left   ans
    ||                      0       0       0           0
    |    |                  0       1       1           1
    |        |              0       2       2           2
    |            |          0       3       3           3
         |       |          1       3       2           3
             |   |          2       3       1           3
             |        |     2       4       2           3
             |   由于没有冲突,右指针继续右移,跳出循环
*/

/*
     1   2   3   2   1      left    right   right-left   ans
    ||                      0       0       0           0
    |    |                  0       1       1           1
    |        |              0       2       2           2
    |            |          0       3       3           3
         |       |          1       3       2           3
             |   |          2       3       1           3
             |        |     2       4       2           3
             |   由于没有冲突,右指针继续右移,跳出循环
*/

int main()
{
    int num[maxn] , cases, n ;
    scanf("%d",&cases);
    while(cases--)
    {
        int n;
        scanf("%d",&n);
        rep(i,0,n) scanf("%d",&num[i]);

        long long ans=0;
        set <int > myset;               //用于检查是否出现重复
        int left=0,right=0;
        while(right<n){                 //时间复杂度O(n)
            while(right<n && !myset.count(num[right])) myset.insert(num[right++]);
                                        //不冲突时,右指针一直向右移动
                                        //右指针最后停留在第一个冲突的位置
            if(right-left>ans) ans=right-left;
            myset.erase(num[left++]);       //左指针移动
        }
        cout<<ans<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值