Problem Author: | Oleksandr Tymkovych |
Prepared by: | Oleksandr Tymkovych |
Editorial by: | Denysov Kostiantyn |
. It is possible to prevent every student from being expelled if and only if \sum_{i=1}^n {s_i} \ge n \cdot m.
Necessity is simple as with every vote the \sum_{i=1}^n {s_i} decreases by and if no one expelled then after rearranging votes, all student statuses are non-negative and then the \sum_{i=1}^n {s_i} - n \cdot m \ge 0.
Let f_i — be statuses of students after all the votes.
For sufficiency, we need to prove that it is possible to rearrange the votes so that all f_i \ge 0 if \sum_{i=1}^n {f_i} \ge 0. Let's divide f_i in two types: positive (f_i \ge 0) and negative (f_i<0). From our condition, we have \sum_{f_i \ge 0} {f_i} \ge -\sum_{f_i < 0} {f_i}. To increase f_i<0 by we can change the vote to decrease the status of person to some person with positive status (from that inequality it always exists). This way, by increasing negative f_i by one we can make them all positive.
From sufficiency, we can also understand how to get minimal cost. When you increase negative f_i you just take the minimal cost of changing among those values who voted for person .
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<int> s(n + 1);
for (int i = 1; i <= n; i++) {
cin >> s[i];
}
vector<vector<int>> V(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> V[i][j];
s[V[i][j]]--;
}
}
vector<vector<int>> G(n + 1);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
int C;
cin >> C;
G[V[i][j]].push_back(C);
}
}
for (int i = 1; i <= n; i++) {
sort(G[i].begin(), G[i].end(), greater<>());
}
set<pair<int, int>> st;
for (int i = 1; i <= n; i++) {
st.insert({s[i], i});
}
auto upd = [&st](auto it, int delta) {
auto [status, id] = *it;
st.erase({status, id});
st.insert({status + delta, id});
};
long long ans = 0;
while (st.begin()->first < 0) {
auto [status, id] = *st.begin();
if (G[id].empty()) {
cout << "-1\n";
return 0;
}
ans += G[id].back();
G[id].pop_back();
upd(st.begin(), 1);
upd(--st.end(), -1);
}
cout << ans << "\n";
}