P1638 逛畫展

尔一發表於2024-07-23

逛畫展

題目描述

博覽館正在展出由世上最佳的 𝑚位畫家所畫的圖畫。
遊客在購買門票時必須說明兩個數字,𝑎 和 b,代表他要看展覽中的第 𝑎 幅至第 𝑏 幅畫(包含 𝑎,𝑏)之間的所有圖畫,而門票的價錢就是一張圖畫一元。
Sept 希望入場後可以看到所有名師的圖畫。當然,他想最小化購買門票的價格。
請求出他購買門票時應選擇的 𝑎,𝑏資料保證一定有解。

若存在多組解,輸出 𝑎 最小的那組。

輸入格式

第一行兩個整數 𝑛,𝑚,分別表示博覽館內的圖畫總數及這些圖畫是由多少位名師的畫所繪畫的。

第二行包含 𝑛 個整數 𝑎𝑖,代表畫第 𝑖 幅畫的名師的編號。

輸出格式

一行兩個整數 a,b。

樣例 #1

樣例輸入 #1

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

樣例輸出 #1

2 7

提示

資料規模與約定

對於 30% 的資料,有 n≤200,m≤20。
對於 60% 的資料,有 n≤10^5,m ≤10^3。
對於 100% 的資料,有 1≤n≤106,1≤ai≤m≤2×103。

#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    vector<int> paintings(n + 1); // 儲存每幅畫對應的名師編號

    for (int i = 1; i <= n; ++i) cin >> paintings[i];

    unordered_map<int, int> cnt; // 記錄每個名師畫作的數量
    int minLen = n + 1; // 初始化最小長度為n+1,即不可能的最大值
    int l = 1, r = 1; // 初始化雙指標
    int ansStart = 1, ansEnd = n; // 初始化答案區間

    // 首先擴充套件右邊界,直到包含所有名師的畫作
    for (end = 1; end <= n; ++end) {
        cnt[paintings[end]]++;
        // 當區間包含所有名師的畫作時,嘗試縮小左邊界
        while (cnt.size() == m) {
            if (end - start + 1 < minLen) {
                minLen = end - start + 1;
                ansStart = start;
                ansEnd = end;
            }
            cnt[paintings[start]]--;
            if (cnt[paintings[start]] == 0) {
                cnt.erase(paintings[start]); // 如果某個名師的畫作數為0,則從雜湊表中刪除
            }
            start++;
        }
    }

    cout << ansStart << " " << ansEnd << endl; 
    return 0;
}

相關文章