7-1 k-good段

67 篇文章 0 订阅
15 篇文章 0 订阅

 题意:

题目给出一段长度为n的序列我们要在这一段序列中随便找出一段子序列使得这一段子序列中的不同的值有k个,同时我们要保证其最长,我们最后输出时如果最长的子序列不唯一可以随意输出。

思路:

处理这种子序列问题我们要用的就是双指针法,我们先定义左右指针,从1开始右指针依次向右移动在这移动过程中我们设置一个类似于map的东西用来记录序列的每一个值出现过几次,当前遍历的值如果在之前出现零次的话我们就使得sum这个值++,sum这个值是用来储存该子序列中不同值的个数。如下图所示;

 

 

如果我们发现sum的值大于了k值我们就移动左指针,将不同的值减去;如下图所示。

 

 

在过程中我们还有一步关键操作。

if(zright-zleft>right-left)//我们要把最大边界保存下来
{
    right=i;
    left=index;
}

 最后我们最大边界即可。

#include<bits/stdc++.h>
using namespace std;
const int INX=3e6;
int a[INX],finds[INX];
int main()
{
    int num1,num2;
    cin>>num1>>num2;
    int left=1,right=1;
    int sum=0;
    int index=1;
    for(int i=1;i<=num1;i++)
    {
        cin>>a[i];
        if(finds[a[i]]==0)
        {
            sum++;
        }
        finds[a[i]]++;
        while(sum>num2)
        {
            finds[a[index]]--;
            if(finds[a[index]]==0)
            {
                sum--;
            }
            index++;
        }
        if(i-index>right-left)
            {
                right=i;
                left=index;
            }
    }
    cout<<left<<" "<<right;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

B程洪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值