逛画展(双指针)

# 逛画展

## 题目描述

博览馆正在展出由世上最佳的 $m$ 位画家所画的图画。

游客在购买门票时必须说明两个数字,$a$ 和 $b$,代表他要看展览中的第 $a$ 幅至第 $b$ 幅画(包含 $a,b$)之间的所有图画,而门票的价钱就是一张图画一元。

Sept 希望入场后可以看到所有名师的图画。当然,他想最小化购买门票的价格。

请求出他购买门票时应选择的 $a,b$,数据保证一定有解。

若存在多组解,**输出 $a$ 最小的那组**。

## 输入格式

第一行两个整数 $n,m$,分别表示博览馆内的图画总数及这些图画是由多少位名师的画所绘画的。

第二行包含 $n$ 个整数 $a_i$,代表画第 $i$ 幅画的名师的编号。

## 输出格式

一行两个整数 $a,b$。

## 样例 #1

### 样例输入 #1

```
12 5
2 5 3 1 3 2 4 1 1 5 4 3
```

### 样例输出 #1

```
2 7
```

## 提示

#### 数据规模与约定

- 对于 $30\%$ 的数据,有 $n\le200$,$m\le20$。
- 对于 $60\%$ 的数据,有 $n\le10^5$,$m\le10^3$。
- 对于 $100\%$ 的数据,有 $1\leq n\le10^6$,$1 \leq a_i \leq m\le2\times10^3$。

//P1638 逛画展
//区间伸缩,运用双指针进行伸缩区间,从前往后找,然后记录每一个符合条件的区间
//记录完成之后再删除队头的值,进入下一区间
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=1e9+7;
string s;
int n,t,a[N],f[N],res,num=1,ans=0x3f3f3f,m,ll,rr,l=1,r=1;
bool vis[N];
signed main()
{
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];f[a[1]]=1;
    while(l<=n&&r<=n){
        if(num==m){
            if(ans>r-l+1) ans=r-l+1,ll=l,rr=r;
            f[a[l]]--;
            if(f[a[l++]]==0) num--;
        }
        else{
            f[a[++r]]++;
            if(f[a[r]]==1) num++;   
        }
    }
    cout<<ll<<" "<<rr;
    return 0;
}
// 滑动窗口
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=1e9+7;
string s;
int n,t,a[N],f[N],res,num,ans=0x3f3f3f3f,m,l=1,ll,rr;
bool vis[N];
signed main()
{
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(f[a[i]]==0) num++;
        f[a[i]]=i;
        while(l<f[a[l]]) l++;
        if(num==m&&ans>i-l+1) ans=i-l+1,ll=l,rr=i;
    }
    cout<<ll<<" "<<rr;
    return 0;
}

 

posted @ 2023-07-19 17:22  o-Sakurajimamai-o  阅读(67)  评论(0)    收藏  举报
-- --