この問題は主に尺取り法を問います。
単に を全探索してしまうと となり、時間制限に間に合いません。では、どうしたらよいでしょうか?
問題の制約から、区間 に対して以下の性質があることが分かります。
よってすべての区間において単調性があることがうかがえます。
またこの問題では条件を満たす区間の数え上げを要求しているので、これは尺取り法というアルゴリズムを用いて実装することができます。
任意の整数 の個数カウントですが、制約上これは連想配列などを用いることが適切です。以上から次の手続きを行えばよいです。
便宜上、区間 に出現する任意の整数 の個数を と表します。
かつ が 以下である限り、 を ずつ増やすことを繰り返す
もし となるならば、 を 増やす
ならば を だけ増やす準備をするため、を 減らす
明らかにこの手続きを踏むことにより、最初に出てくる の個数の上限を超えないかつ 以上であることが見て取れます。
厳密にいうと、以下のようなことが分かります。
手続きを見ると と全探索した時と同じ計算量に見えますが、実は であることが分かっています。
(この計算量のヒミツについては、他の方々の記事などを参考にしてください。ここでは省略します)
以上からこの問題は で実装することが可能です。
xxxxxxxxxx
//[0,n)
using namespace std;
using ll = long long;
int main(){
int N,M; cin >> N >> M;
vector<int> A(N); rep(i,N) cin >> A[i];
map<int,int> mp;
int r = 0;
ll ans = 0;
mp[A[0]]++;
rep(l,N){
while(r+1 < N && mp[A[r+1]]+1 <= M) mp[A[r+1]]++,r++;
ans += r-l;
if(l == r) r++;
else mp[A[l]]--;
}
cout << ans;
}