牛客周赛 Round 104
A. 小红的不动点
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int a[4]{};
int ans = 0;
for (int i = 0; i < 4; ++ i) {
std::cin >> a[i];
ans += a[i] == i + 1;
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
// std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
B. 小红的不动点构造
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n, k;
std::cin >> n >> k;
std::vector<int> a(n);
std::ranges::iota(a, 0);
do {
int cnt = 0;
for (int i = 0; i < n; ++ i) {
cnt += a[i] == i;
}
if (cnt == k) {
for (int i = 0; i < n; ++ i) {
std::cout << a[i] + 1 << " \n"[i == n - 1];
}
return;
}
} while (std::next_permutation(a.begin(), a.end()));
std::cout << -1 << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
// std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
C. 小红的不动点分配
题意:\(2n\)个数分配到\(2\)个长度为\(n\)的数组,使得值等于下标的位置最多。
记录每个数的出现次数,\(i\)放到第\(i\)个位置有贡献。每个下标最多\(2\)的贡献。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n;
std::cin >> n;
std::vector<int> cnt(n + 1);
for (int i = 0; i < 2 * n; ++ i) {
int x;
std::cin >> x;
if (x <= n) {
++ cnt[x];
}
}
int ans = 0;
for (int i = 1; i <= n; ++ i) {
ans += std::min(2, cnt[i]);
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
// std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
D. 小红的矩阵不动点
题意:给你一个矩阵,你可以交换两个元素,使得\(a[i][j] = \min(i, j)\)的位置最多。
记\(500\)个\(set\),如果\(a[i][j] \ne \min(i, j)\),就将\(\min(i, j)\)插入\(set[a[i][j]]\)。
那么先判断能不能交换两个位置使得答案加二,也就是对于\(set[i]\)的里每个\(x\),\(set[x]\)有没有包含\(i\)。
如果没有,判断能不能使得答案加二,也就是对于\(a[i][j] \ne \min(i, j)\),看\(set[\min(i, j)]\)有没有至少一个元素 。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n, m;
std::cin >> n >> m;
std::vector a(n, std::vector<int>(m));
int ans = 0;
std::vector<std::set<int>> s(500);
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
std::cin >> a[i][j];
-- a[i][j];
if (a[i][j] == std::min(i, j)) {
++ ans;
} else {
s[a[i][j]].insert(std::min(i, j));
}
}
}
for (int i = 0; i < 500; ++ i) {
for (auto & x : s[i]) {
if (s[x].count(i)) {
std::cout << ans + 2 << "\n";
return;
}
}
}
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
if (a[i][j] != std::min(i, j) && s[std::min(i, j)].size()) {
std::cout << ans + 1 << "\n";
return;
}
}
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
// std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
E. 小红的不动点权值
题意:一个数组的值为给它排序后,\(a_i = i\)的位置个数。给你一个排列,求所有子数组的价值和。
因为是排列,如果排序后\(a_i = i\),那么\([1, i]\)都出现了。所以从小到大枚举值,记录每个值出现的位置,如果\([1, i]\)最左边的位置在\(l\),最右边在\(r\),则有\(l \times (n - r + 1)\)个数组有贡献。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
std::vector<int> p(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
-- a[i];
p[a[i]] = i;
}
i64 ans = 0;
int l = n, r = -1;
for (int i = 0; i < n; ++ i) {
l = std::min(l, p[i]);
r = std::max(r, p[i]);
ans += (i64)(l + 1) * (n - r);
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
// std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
F. 小红的树不动点
题意:给你一棵树,根为\(n\)。一个点的价值为其子树所有元素排序后\(a_i = i\)的个数。求总价值。
也是从小到大枚举元素,那么子树包含\([1, i\)的里根最远的点就是\([1, i]\)的\(lca\)。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n;
std::cin >> n;
std::vector<std::vector<int>> adj(n + 1);
for (int i = 1; i < n; ++ i) {
int u, v;
std::cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
const int lg = std::__lg(n) + 1;
std::vector fa(n + 1, std::array<int, 20>{});
std::vector<int> d(n + 1);
auto dfs = [&](auto & self, int u) -> void {
for (auto & v : adj[u]) {
if (v == fa[u][0]) {
continue;
}
d[v] = d[u] + 1;
fa[v][0] = u;
for (int i = 1; i <= lg; ++ i) {
fa[v][i] = fa[fa[v][i - 1]][i - 1];
}
self(self, v);
}
};
d[n] = 1;
dfs(dfs, n);
auto lca = [&](int u, int v) -> int {
if (d[u] < d[v]) {
std::swap(u, v);
}
for (int i = lg; i >= 0; -- i) {
if (d[fa[u][i]] >= d[v]) {
u = fa[u][i];
}
}
if (u == v) {
return u;
}
for (int i = lg; i >= 0; -- i) {
if (fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
};
i64 ans = d[1];
for (int i = 2, u = 1; i <= n; ++ i) {
u = lca(u, i);
ans += d[u];
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
// std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}

浙公网安备 33010602011771号