Topics
- Given n students with smartness values
a[i]
- m topics numbered 1 to m
- Student i is proficient in topic T if
a[i] mod T = 0
- Find a team where:
- For each topic, at least one team member is proficient
- Minimize the maximum difference in smartness between any two team members
Idea
Let’s use a sliding window technique on sorted smartness values to track how many topics are being covered as we add and remove a student.
As we expand the team by moving the right pointer, we check the factors of each student’s smartness to determine which topics they help cover. If all topics are covered, we calculate the difference between the highest and lowest smartness values in the current team. Then, we attempt to reduce the size of the team from the left to see if the range can be further minimized while still covering all topics.
Algorithm steps
- Preprocessing: Sort students by smartness
- For each student, find all factors of their smartness value that are ⇐ m
- Sliding Window:
- Use two pointers (l, r) to maintain a window of students
- For a valid team, difference is
a[r] - a[l]
(we want to minimize this) - For each window:
- Track count of students proficient in each topic using
counts[]
- Track total number of covered topics (
runner
)
- Track count of students proficient in each topic using
- When window covers all topics, i.e.
runner == m
:- Update minimum difference:
best = min(best, arr[r] - arr[l])
- Try shrinking window from left
- Update minimum difference:
- When adding student to window (right side):
- Find all factors ⇐ m of their smartness
- Increment
counts
for each factor - If
counts[factor]
changes 0 to 1, incrementrunner
- When removing student from window (left side):
- Decrement
counts
for each factor - If
counts[factor]
changes 1 to 0, decrementrunner
- Decrement
Time Complexity
- Sorting:
- Factor calculation:
- Sliding window:
- Overall:
Code
void solve(){
int n, m;
cin >> n >> m;
vector<int> arr(n);
for (int i = 0; i < n; ++i)
cin >> arr[i];
sort(all(arr));
// get all factors <= m, for each element
vector<vi> factors(n);
int curr;
for (int i = 0; i < n; ++i) {
curr = arr[i];
for (ll j = 1; j * j <= curr; ++j) {
if (j > m)
break;
if (curr % j == 0) {
factors[i].pb(j);
if (j * j != curr and curr / j <= m)
factors[i].pb(curr / j);
}
}
}
// sliding window
int runner = 0;
int best = INT_MAX;
int l = 0;
vector<int> counts(m + 1);
for (int r = 0; r < n; ++r) {
for (int &f : factors[r]) {
if (counts[f] == 0) {
runner++;
}
counts[f]++;
}
while (runner == m) {
best = min(best, arr[r] - arr[l]);
// shrink
for (int &f : factors[l]) {
counts[f]--;
if (counts[f] == 0) {
runner--;
}
}
l++;
}
}
cout << (best == INT_MAX ? -1 : best) << '\n';
}