Topics

Given an array of integers, your task is to calculate the number of subarrays that have at most distinct values.

Idea

This problem is a classic application of the sliding window with variable window size (snake framework) technique. The key insight is that we can efficiently count valid subarrays by maintaining a window where the number of distinct elements never exceeds k.

This problem can be efficiently solved using the sliding window technique with variable window size. The approach maintains two pointers (tail and head) that define the current window boundaries. We expand the window by moving head rightwards as long as the number of distinct elements remains ≤ k. When we can’t expand further, all subarrays starting at tail and ending at any position up to head are valid, which we count in bulk using (head - tail + 1). Then we move tail rightwards, adjusting our frequency counts accordingly. Basically, each expansion phase finds the maximum valid window for the current tail position.

The works because the window property ( k distinct elements) satisfies the applicability condition - shrinking from the left can’t make a valid window invalid.

Time Complexity:
Space Complexity: extra space

Code

void solve() {
  int n, k;
  cin >> n >> k;
  vector<int> arr(n);
  for (int i = 0; i < n; ++i) {
    cin >> arr[i];
  }
 
  ll ans = 0;
  int tail = 0, head = -1;
  map<int, int> freq;
  int d_count = 0;
 
  while (tail < n) {
    // Expand until we have more than k distinct elements
    while (head + 1 < n) {
      // Check if adding the next element would exceed k distinct elements
      if (freq[arr[head + 1]] == 0 && d_count == k)
        break;
 
      // Safe to add next element
      head++;
      if (freq[arr[head]] == 0)
        d_count++;
      freq[arr[head]]++;
    }
 
    // Process window: all valid subarrays ending at positions [tail...head]
    // For each valid window [tail...head], we have (head-tail+1) valid
    // subarrays
    ans += (head - tail + 1);
 
    // undo effect of tail
    if (tail <= head) {
      freq[arr[tail]]--;
      if (freq[arr[tail]] == 0)
        d_count--;
    }
 
    tail++;
    head = max(head, tail - 1);
  }
 
  cout << ans << endl;
}