牛客周赛 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;
}
posted @ 2025-08-10 21:00  maburb  阅读(101)  评论(0)    收藏  举报