競プロ覚書

思考整理

典型90問 - 034 There are few types of elements(★4)

https://atcoder.jp/contests/typical90/tasks/typical90_ah
ベーシックなしゃくとり法

【問題】
数列の区間のうち、含まれる値の種類がK種類以下である最長の連続部分列を求めよ。
【典型ポイント】
しゃくとり法
【方針】
見たまんま、しゃくとり法の典型問題
種類の数え方には連想配列を用いる。集合だと削除処理ができないため。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<long long, long long>;
constexpr char ln =  '\n';
constexpr long long MOD = 1000000007;
constexpr long long INF = 1000000000 + 100;
constexpr long long LINF = 1000000000000000000 + 100;
#define all(v) v.begin(), v.end()
#define rep(i, n) for(int i=0;i<(n);i++)
#define rept(i, j, n) for(int i=(j); i<(n); i++)
#define rrep(i, n) for(int i=(n); i>=0; i--)
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }


int main(){
    int N, K; cin >> N >> K;
    vector<ll> A(N);
    rep(i, N){
        cin >> A[i];
    }

    int right = 0, res = -1;
    map<int, int> mp; int cnt = 0;
    for(int left=0; left<N; left++){//[left, right)
        while(right<N){
            if(mp[A[right]]==0 and cnt == K)break;
            if(mp[A[right]] == 0)cnt++;
            mp[A[right]]++;
            right++;
        }
        chmax(res, right - left);

        if (left == right) right++;
        mp[A[left]]--;
        if(mp[A[left]] == 0)cnt--;
    }
    cout << res << ln;
}