B - Array
You’ve got an array a, consisting of n integers: a1, a2, …, an. Your task is to find a minimal by inclusion segment [l, r] (1 ≤ l ≤ r ≤ n) such, that among numbers al,  al + 1,  …,  ar there are exactly k distinct numbers.
Segment [l, r] (1 ≤ l ≤ r ≤ n; l, r are integers) of length m = r - l + 1, satisfying the given property, is called minimal by inclusion, if there is no segment [x, y] satisfying the property and less then m in length, such that 1 ≤ l ≤ x ≤ y ≤ r ≤ n. Note that the segment [l, r] doesn’t have to be minimal in length among all segments, satisfying the given property.
Input
The first line contains two space-separated integers: n and k (1 ≤ n, k ≤ 105). The second line contains n space-separated integers a1, a2, …, an — elements of the array a (1 ≤ ai ≤ 105).
Output
Print a space-separated pair of integers l and r (1 ≤ l ≤ r ≤ n) such, that the segment [l, r] is the answer to the problem. If the sought segment does not exist, print “-1 -1” without the quotes. If there are multiple correct answers, print any of them.
Examples
Input
4 2
1 2 2 3
Output
1 2
Input
8 3
1 1 2 2 3 3 4 5
Output
2 5
Input
7 4
4 7 7 4 7 4 7
Output
-1 -1
Note
In the first sample among numbers a1 and a2 there are exactly two distinct numbers.
In the second sample segment [2, 5] is a minimal by inclusion segment with three distinct numbers, but it is not minimal in length among such segments.
In the third sample there is no segment with four distinct numbers.
Sponsor

题目大意:
给出一行n个数,要求在这n个数中找出正好含有m个不同的数的子序列。
要求:不需要输出最短的,但是所求字符串必须在当前选择下是最短的,没有冗余。输出任意一种结果。

做题时:

  1. 这道题主要还是死在英语上,开始我以为是求含有m个不同的数的子序列字符串,wa了,
  2. 后来以为是求字符串和最小且含有m个不同的数的子序列,因为clear()写循环里面还写了两个超时了,然后优化了一下,过了20组,还是wa了。
  3. 再后来发现数据很大,范围超了,所以不可能是求和最小,于是就是求要求在这n个数中找出正好含有m个不同的数的子序列。

思路

这道题可以直接从第一个开始找,找到满足m个不同位置的子序列最末端,也就是找到r的位置,然后再从第m往前找l的位置即可。

#include <bits/stdc++.h>
#define pb(a) push_back(a)
#define pf push_front
#define beg begin
#define e end
#define rb rbegin0
#define re rend
#define nd cout<<endl
#define all(s) s.begin(),s.end()
#define pi acos(-1.0)
#define MaxN 0x3f3f3f3f
#define MinN 0xc0c0c0c0
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N=2e5+15;
int n,m,l,r,sum,f;
int a[N],b[N];
int main()
{
   
    cin>>n>>m;
    for(int i=1; i<=n; i++)
        cin>>a[i];
    int p=2;
    for(int i=1; i<=n; i++)
    {
   
        if(b[a[i]])
            continue;
        b[a[i]]=1;
        sum++;
        if(sum==m)
        {
   
            r=i;
            f=1;
            break;
        }
    }
    memset(b,0,sizeof(b));
    sum=0;
    for(int i=r; i>=1; i--)
    {
   
        if(b[a[i]])
            continue;
        b[a[i]]=1;
        sum++;
        if(sum==m)
        {
   
            l=i;
            break;
        }
    }
    if(f)
        cout<<l<<" "<<r<<endl;
    else
        cout<<-1<<" "<<-1<<endl;
    return 0;
}
  1. 小结一下,关于做题,还是实行

    1. 审题,题意要反复斟酌,推敲,最后确定。
    2. 写代码前做一个伪代码,或者脑海中有一个整体的思路,如果是模拟很复杂,那么就需要写在纸上,将各个条件分析清楚,以及条件之间的关系。
    3. 写完代码,需要再次花一两分种做一个整体检查。
      检查内容:
      1. 数组大小(空间是否小,否则是否大)
      2. 时间复杂度
      3. 清零(空)
  2. 对于这道题目,犯的小错误:

    1. 超时
      1. 原因:map的clear() 在for里面 使用了两次,不必要的浪费时间复杂度。 当时应该检查一次,考虑清楚要不要去掉clear(),因为使用会造成时间复杂度过大,但后来想显然不用。
      2.审题时对数据范围出现了一个偏差,对于求子序列的和,做出了一个错误的判断。