A. Problem Generator
思路
A:纯纯模拟,不多解释。
code
inline void solve() {
int n, m; cin >> n >> m;
vector<int> cnt(26);
string s; cin >> s;
for (char c : s) cnt[c - 'A'] += 1;
ll ans = 0;
for (int i = 0; i < 7; i ++ ) {
ans += max(m - cnt[i], 0);
}
cout << ans << endl;
return;
}
B. Choosing Cubes
思路
Q:怎么还是模拟?
A:我怎么知道。
要解决这个问题,其实只要统计a[f]的数量和大于等于a[f]的数量即可。因为最后是要降序排序的,然后分讨就行。
code
inline void solve() {
int n, m, k; cin >> n >> m >> k;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> a[i];
int sum = 0, pre = 0;
for (int i = 1; i <= n; i ++ ) {
if (a[i] >= a[m]) pre += 1;
if (a[i] == a[m]) sum += 1;
}
if (k >= pre) cout << "YES\n";
else if (k > pre - sum && k < pre) cout << "MAYBE\n";
else cout << "NO\n";
return;
}
C. Sofia and the Lost Operations
思路
Q:将数组a变成数组b的最基本条件是什么?
A:给的数组d中要有a变成b没有的元素。对于样例一,d数组至少要有1,2。
Q:那就只要检查这个就行了么?
A:当然不对,数组d上的元素是都要被利用上的,对于样例一,如果再给一个5,a就完全不能变成b了。
Q:那要怎么做?
A:你发现了么,只要是5,1,2或者1,5,2就能实现“覆盖”。也就是说,如果出现了b中没有的元素,只要后面有b中的元素就可以了。
code
inline void solve() {
int n; cin >> n;
vector<int> a(n + 1), b(n + 1);
map<int, int> need;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
for (int i = 1; i <= n; i ++ ) {
cin >> b[i];
if (a[i] != b[i]) need[b[i]] += 1;
else {
if (!need.count(b[i])) need[b[i]] = 0;
}
}
bool last = false;
int q; cin >> q;
for (int i = 1; i <= q; i ++ ) {
int x; cin >> x;
if (need.count(x)) {
if (need[x]) need[x] -= 1;
last = false;
}else last = true;
}
if (last) return cout << "NO\n", void();
for (auto [t, c] : need) {
if (c != 0) return cout << "NO\n", void();
}
cout << "YES\n";
return;
}
D. GCD-sequence
思路
Q:怎么又又是模拟?
A:首先拿出gcd数组,我们可以得到的是b[i + 1] < b[i]的数量,然后模拟删除,观察这个数量是否会变成0即可。
code
inline void solve() {
int n; cin >> n;
vector<int> a(n + 1), b(n);
for (int i = 1; i <= n; i ++ ) cin >> a[i];
for (int i = 1; i < n; i ++ ) b[i] = gcd(a[i], a[i + 1]);
int cnt = 0;
for (int i = 2; i < n; i ++ ) cnt += (b[i] < b[i - 1]);
bool ok = false;
if (cnt - (b[2] < b[1]) == 0 || cnt - (b[n - 1] < b[n - 2]) == 0) ok = true;
for (int i = 2; i < n; i ++ ) {
int tmp = cnt, cur = gcd(a[i - 1], a[i + 1]);
tmp -= (b[i] < b[i - 1]);
if (i - 2 >= 1) {
tmp -= (b[i - 1] < b[i - 2]);
tmp += (cur < b[i - 2]);
}
if (i + 1 < n) {
tmp -= (b[i + 1] < b[i]);
tmp += (cur > b[i + 1]);
}
if (tmp == 0) ok = true;
}
if (ok) cout << "YES\n";
else cout << "NO\n";
return;
}
E. Permutation of Rows and Columns
思路
A:我直接抢着说了,这题就是一眼出的题吧。我们要做的有1.判断两个矩阵“对应行”元素是否一致。2.用数组映射交换列即可。
code
inline void solve() {
int n, m; cin >> n >> m;
vector<vector<int> > a(n + 1, vector<int>(m + 1)), b(n + 1, vector<int>(m + 1));
map<int, int> col, row;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
cin >> a[i][j];
col[a[i][j]] = j, row[a[i][j]] = i;
}
}
bool ok = true;
for (int i = 1; i <= n; i ++ ) {
int loc = -1;
for (int j = 1; j <= m; j ++ ) {
cin >> b[i][j];
if (loc == -1) loc = row[b[i][j]];
else if (row[b[i][j]] != loc) ok = false;
}
}
vector<int> lie(m + 1);
for (int i = 1; i <= m; i ++ ) {
lie[i] = col[b[1][i]];
}
for (int i = 2; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
if (b[i][j] != a[row[b[i][j]]][lie[j]]) ok = false;
}
}
if (ok) cout << "YES\n";
else cout << "NO\n";
return;
}
F1. Field Division (easy version)
思路
Q:怎么给才能使得增加呢?
A:由观察可知,只有满足两种情况才可以,假设我们处于从上往下遍历行中
1.该元素是该行喷泉的最左边
2.该元素是接下来几行的最小(不能有相等)
code
很史
inline void solve() {
int n, m, k; cin >> n >> m >> k;
vector<array<int, 3>> a(k);
map<int, int> row;
for (int i = 0; i < k; i ++ ) {
cin >> a[i][0] >> a[i][1];
if (!row.count(a[i][0])) row[a[i][0]] = a[i][1];
else row[a[i][0]] = min(row[a[i][0]], a[i][1]);
a[i][2] = i;
}
map<int, int> l;
for (auto [t, c] : row) l[c] += 1;
l[1e9] += 1;
ll tot = 0;
int minv = row.rbegin()->second;
for (auto t = row.rbegin(); t != row.rend(); t ++ ) {
minv = min(t->second, minv);
t->second = minv;
}
if (row.rbegin()->first < n) {
tot += (ll)(n - row.rbegin()->first) * m;
}
int last = 0;
for (auto [r, c] : row) {
tot += (ll)(r - last) * (c - 1);
last = r;
}
cout << tot << endl;
sort(a.begin(), a.end());
set<int> vis;
vector<int> ans(k);
for (int i = 0; i < k; i ++ ) {
if (!vis.count(a[i][0])) {
vis.insert(a[i][0]);
l[a[i][1]] -= 1;
if (l[a[i][1]] == 0) l.erase(a[i][1]);
if (l.begin()->first > a[i][1]) ans[a[i][2]] = 1;
}
}
for (int i = 0; i < k; i ++ ) cout << ans[i] << ' ';
cout << endl;
return;
}
写在最后
剩下题解明天补)
cf用umap卡特色,会退化到O(n),1e7再考虑用这个吧,1e5的完全可以map,还打的快()