Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Focus on one value at a time. The final multisets must have equal counts of , so the total number of 's in the whole array already tells you a hard requirement.
If is not divisible by for some value , then there is no way to split all copies of equally. In that case the answer is instantly .
Assume every is divisible by . Then each multiset must end with exactly copies of value .
The chosen subarray is forced into multiset . So for every value , the subarray may contain at most copies of . That condition is also sufficient, because all outside elements can be distributed to fill the remaining quotas.
Now the problem is just: count subarrays where no value exceeds its allowed frequency. Use a sliding window. Expand right, and if the new value exceeds its limit, move left until it doesn't. Add the current window length each step.
Let be the number of times value appears in the whole array.
For the final multisets to be identical, each value must be split equally among them. That means must be divisible by for every . If even one value fails this, the answer is . No clever placement saves you there; arithmetic already killed the plan.
Now suppose every value passes divisibility.
Then each multiset must contain exactly
copies of value .
For a subarray , all its elements are forced into multiset . So if this subarray contains copies of value , we must have
for every value . Otherwise multiset already has too many copies of , and we cannot remove them. Game over.
The important part: this condition is also sufficient.
If the subarray uses copies of in multiset , then outside the subarray there are remaining copies. We need to put:
The total needed outside is
which is exactly how many outside copies exist. Since values are independent, we can do this for every value separately.
So the whole multiset story collapses into a much cleaner problem:
Count subarrays where every value appears at most times.
That is a standard sliding window.
Maintain a window and current frequencies inside it. When we add , only that value's frequency can become invalid. If it exceeds its limit, move right, subtracting frequencies, until the window is valid again.
After fixing the window for this , every subarray ending at and starting at any position from to is valid. There are
such subarrays, so add that to the answer.
Why are all those suffixes valid? Because removing elements from a valid window can only decrease frequencies. It cannot create a new violation. Pretty nice when the problem stops pretending to be about multisets and admits it's just frequency caps.
Complexity is per test case, since each pointer moves right at most times. Memory is because values are between and .
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
vector<int> a(n), total(n + 1, 0);
for (int &x : a) {
cin >> x;
total[x]++;
}
vector<int> limit(n + 1, 0);
bool possible = true;
for (int v = 1; v <= n; v++) {
if (total[v] % k != 0) possible = false;
limit[v] = total[v] / k;
}
if (!possible) {
cout << 0 << '\n';
continue;
}
vector<int> have(n + 1, 0);
ll ans = 0;
int left = 0;
for (int right = 0; right < n; right++) {
int x = a[right];
have[x]++;
while (have[x] > limit[x]) {
have[a[left]]--;
left++;
}
ans += right - left + 1;
}
cout << ans << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
vector<int> a(n), total(n + 1, 0);
for (int &x : a) {
cin >> x;
total[x]++;
}
vector<int> limit(n + 1, 0);
bool possible = true;
for (int v = 1; v <= n; v++) {
if (total[v] % k != 0) possible = false;
limit[v] = total[v] / k;
}
if (!possible) {
cout << 0 << '\n';
continue;
}
vector<int> have(n + 1, 0);
ll ans = 0;
int left = 0;
for (int right = 0; right < n; right++) {
int x = a[right];
have[x]++;
while (have[x] > limit[x]) {
have[a[left]]--;
left++;
}
ans += right - left + 1;
}
cout << ans << '\n';
}
return 0;
}