Codeforces Round 950 (Div. 3)
A. Problem Generator
题意:每组题由A~G的题目组成,现在已经有n个题目,需要组m组题目,最少需要添加多少题目;
思路:记录一下每种题目的数量,看距离m差多少即可;
AC code:
void solve() {
int n, m; cin >> n >> m;
string s; cin >> s;
sort(s.begin(), s.end());
map<char, int> mp;
int cnt = 0;
for (auto c : s) mp[c] ++;
for (char c = 'A'; c <= 'G'; c ++) {
if (mp[c] < m) cnt += m - mp[c];
}
cout << cnt <<endl;
}
B. Choosing Cubes
题意:n个正方体,初始下标为f的正方体为最爱,倒序排列后前k项是否可能出现最爱的正方体;
思路:记录最爱的正方体的数值以及每种正方体的大小,倒序排列后移除前k项看最爱的正方体数值是否可能存在即可;
AC code:
void solve() {
int n, f, k; cin >> n >> f >> k;
vector<int> a(n + 1);
map<int, int> mp;
for (int i = 1; i <= n; i ++) cin >> a[i], mp[a[i]] ++;
int pos = a[f];
int cnt = mp[pos];
sort(a.begin() + 1, a.end(), greater<int>());
for (int i = 1; i <= k; i ++) {
mp[a[i]] --;
}
if (cnt == mp[pos]) cout << "NO" << endl;
else {
if (mp[pos]) cout << "MAYBE" << endl;
else cout << "YES" << endl;
}
}
C. Sofia and the Lost Operations
题意:最初给出n个整数序列a,以及m次的修改序列,每个序列对应两个元素c,d,修改操作为 a c a_c ac=d,现在已知序列a,d以及修改后的序列b,能否找出可能符合条件的序列c;
思路:
已经通过修改变为正确的元素,以及修改后依然正确的元素,在他们之前任意修改该元素不会影响最终的序列;
所以我们每次取出下标下标最大的需要修改的元素,再取出下标最大的相同元素,剩下的元素填充到已经修改的元素前面即可;
AC code:
void solve() {
int n; cin >> n;
vector<int> a(n + 1), b(n + 1);
for (int i = 1; i <= n; i ++) cin >> a[i];
for (int i = 1; i <= n; i ++) cin >> b[i];
int m; cin >> m;
map<int, priority_queue<int>> mp;
vector<int> c(m + 1, -1), d(m + 1);
for (int i = 1; i <= m; i ++) {
cin >> d[i];
mp[d[i]].push(i);
}
for (int i = 1; i <= n; i ++) {
if (a[i] != b[i]) {
if (mp[b[i]].empty()) {
cout << "NO" << endl;
return;
} else {
int t = mp[b[i]].top();
mp[b[i]].pop();
c[t] = i;
}
}
}
for (int i = 1; i <= n; i ++) {
if (a[i] == b[i]) {
if (!mp[b[i]].empty()) {
int t = mp[b[i]].top();
mp[b[i]].pop();
c[t] = i;
}
}
}
int pos = -1;
for (int i = m; i >= 1; i --) {
if (c[i] == -1) {
if (pos == -1) {
cout << "NO" << endl;
return;
} else {
c[i] = pos;
}
} else {
pos = c[i];
}
}
cout << "YES" << endl;
}
D. GCD-sequence
题意:一个长度为n的整数序列的GCD序列定义为长度为n-1的gcd(ai, ai+1)序列,现在最多允许删除原序列的一个元素,使得新的gcd序列非递减;
思路:
找到第一个不符合条件的gcd元素下标pos,可能的修改有删除pos -1,pos,pos + 1三种情况,枚举删除后的序列是否成立即可;
注意,当pos = n时,对于第n-1元素不存在去寻找n+2的元素,直接返回true;
AC code:
int gcd(int a, int b) {
if (b) while ((a%=b)&&(b%=a)); return a + b;
}
bool delet(int pos) {
int last = -1, l = 1;
while (l < n) {
if (l == pos) l ++;
else if (l + 1 == pos) {
if (l + 1 == n) return true;
int ca = gcd(a[l], a[l + 2]);
if (last == -1) last = ca;
else if (last > ca) return false;
last = ca;
l ++;
} else {
int ca = gcd(a[l], a[l + 1]);
if (last == -1) last = ca;
else if (last > ca) return false;
last = ca;
l ++;
}
}
return true;
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i ++) cin >> a[i];
int last = gcd(a[1], a[2]), pos = -1;
for (int i = 2; i < n; i ++) {
if (gcd(a[i], a[i + 1]) < last) {
pos = i;
break;
}
last = gcd(a[i], a[i + 1]);
}
if (pos == -1) {
cout << "YES" << endl;
return;
}
if (delet(pos) || delet(pos - 1) || (pos < n && delet(pos + 1))) {
cout << "YES" << endl;
return;
}
cout << "NO" << endl;
}
E. Permutation of Rows and Columns
题意:给出AB两个二维矩阵,是否有可能通过交换行和列的操作使得A矩阵等于B矩阵;
思路:以每个行列为一个集合,以每个行列的最小元素为基准,先把行按照B排列,再把列按照B排列,最后验证操作后的A序列是否等于B序列即可;
AC code :
void solve() {
int n, m; cin >> n >> m;
vector<vector<int>> a(n + 1, vector<int>(m + 1, 0));
vector<vector<int>> b(n + 1, vector<int>(m + 1, 0));
for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) cin >> a[i][j];
for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) cin >> b[i][j];
vector<vector<int>> c(n + 1, vector<int>(m + 1, 0));
vector<vector<int>> d(n + 1, vector<int>(m + 1, 0));
map<int, int> row, col;
for (int i = 1; i <= n; i ++) {
int mn = n*m;
for (int j = 1; j <= m; j ++) mn = min(mn, b[i][j]);
row[mn] = i;
}
for (int j = 1; j <= m; j ++) {
int mn = n*m;
for (int i = 1; i <= n; i ++) mn = min(mn, b[i][j]);
col[mn] = j;
}
for (int i = 1; i <= n; i ++) {
int mn = n*m;
for (int j = 1; j <= m; j ++) mn = min(mn, a[i][j]);
if (!row[mn]) {
cout << "NO" << endl;
return;
}
c[row[mn]] = a[i];
}
for (int j = 1; j <= m; j ++) {
int mn = n*m;
for (int i = 1; i <= n; i ++) mn = min(mn, c[i][j]);
if (!col[mn]) {
cout << "NO" << endl;
return;
}
for (int i = 1; i <= n; i ++) d[i][col[mn]] = c[i][j];
}
for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) {
if (d[i][j] != b[i][j]) {
cout << "NO" << endl;
return;
}
}
cout << "YES" << endl;
}