Codeforces Round 1062 (Div. 4)


A. Square?

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int a, b, c, d;
	std::cin >> a >> b >> c >> d;
	if (a == b && b == c && c == d) {
		std::cout << "Yes\n";
	} else {
		std::cout << "NO\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. Your Name

题意:判断两个字符串是不是组成的字符一样。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n;
	std::cin >> n;
	std::string s, t;
	std::cin >> s >> t;
	int cnt[26]{};
	for (auto & c : s) {
		++ cnt[c - 'a'];
	}

	for (auto & c : t) {
		if ( -- cnt[c - 'a'] < 0) {
			std::cout << "NO\n";
			return;
		}
	}

	std::cout << "YES\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. Isamatdin and His Magic Wand!

题意:一个数组,你可以交换两个奇偶性不同的数,求交换任意次数组的最小字典序。

如果只有偶数或者奇数无法操作,否则一定可以达到升序。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n;
	std::cin >> n;
	std::vector<int> a(n);
	for (int i = 0; i < n; ++ i) {
		std::cin >> a[i];
	}

	bool f[2]{};
	for (auto & x : a) {
		f[x & 1] = 1;
	}

	if (f[0] && f[1]) {
		std::ranges::sort(a);
	}

	for (int i = 0; i < n; ++ i) {
		std::cout << a[i] << " \n"[i == n - 1];
	}
}

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. Yet Another Array Problem

题意:找一个最小的大于\(1\)的数,使得数组里有一个数和它互质。

这个数一定是一个质数,如果不是质数,则可以用它的最小质因子替换它,这样依然和另一个数互质。
那么枚举质数即可,因为\(a_i \leq 10^{18}\),其包含的不同质因子不超过\(20\)个,那么很快就能找到答案。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

std::vector<int> minp, primes;

void sieve(int n) {
    minp.assign(n + 1, 0);
    primes.clear();
    
    for (int i = 2; i <= n; ++ i) {
        if (minp[i] == 0) {
            minp[i] = i;
            primes.push_back(i);
        }
        
        for (auto p : primes) {
            if (i * p > n) {
                break;
            }
            minp[i * p] = p;
            if (p == minp[i]) {
                break;
            }
        }
    }
}


void solve() {
	int n;
	std::cin >> n;
	std::vector<i64> a(n);
	for (int i = 0; i < n; ++ i) {
		std::cin >> a[i];
	}

	for (auto & p : primes) {
		for (int i = 0; i < n; ++ i) {
			if (std::gcd(a[i], p) == 1) {
				std::cout << p << "\n";
				return;
			}
		}
	}
	std::cout << -1 << "\n";
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	sieve(1000);
	std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}

E. khba Loves to Sleep!

题意:\([0, x]\)上有\(n\)个点,你需要选\(k\)个不同的位置,使得这\(n\)个点到其中一个位置的最小距离最大。

考虑二分。
先把数组排序,如果二分距离为\(d\),对于两个点\(a_i, a_{i+1}\)之间,可以选的位置为\([a_i + d, a_{i+1} - d]\)。判断这些位置够不够\(k\)个并且记录一下方案就行。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n, k, x;
	std::cin >> n >> k >> x;
	std::vector<int> a(n);
	for (int i = 0; i < n; ++ i) {
		std::cin >> a[i];
	}

	std::ranges::sort(a);
	
	if (a.back() != x) {
		a.push_back(2 * x);
	}

	auto check = [&](int d, bool flag) -> std::pair<bool, std::vector<int>> {
		std::vector<int> res;
		if (d == 0) {
			if (flag) {
				for (int i = 0; i < k; ++ i) {
					res.push_back(i);
				}
			}

			return {true, res};
		}
		int last = -2 * x;
		int cnt = 0;
		for (int i = 0; i < a.size(); ++ i) {
			int l = std::max(0, last + d), r = std::min(x, a[i] - d);
			if (l <= r) {
				cnt += r - l + 1;
				if (flag) {
					while (l <= r && res.size() < k) {
						res.push_back(l);
						++ l;
					}
				}
			}

			last = a[i];
		}

		return {cnt >= k, res};
	};

	int lo = 0, hi = x;
	while (lo < hi) {
		int mid = lo + hi + 1 >> 1;
		if (check(mid, false).first) {
			lo = mid;
		} else {
			hi = mid - 1;
		}
	}

	auto ans = check(lo, true).second;
	for (int i = 0; i < k; ++ i) {
		std::cout << ans[i] << " \n"[i == k - 1];
	}
}

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. Tree, TREE!!!

题意:对于一棵树,求对于每个点为根的情况下,选任意\(k\)个点能凑出多少不同的\(lca\)。求每个点的答案的和。

考虑对于\(u\),有多少点为根选\(k\)个点可以凑出\(lca = u\)
那么可以先任意选一个点为根,比如\(1\)。然后\(dfs\)一下记录子树节点个数。那么对于\(u\)子树外的点,不管是谁为根\(u\)的子树依然是这个样子,那么如果\(size_u \geq k\),其它\(n - size_u\)个都可以作为答案。对于\(u\)的一个儿子\(v\),它的子树的任意一个点为根,\(u\)的子树就是\(n - size_v\)个点。那么如果\(n - size_v \geq k\),有\(size_v\)个答案。最后以\(u\)为根显然也是可以的。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n, k;
	std::cin >> n >> k;
	std::vector<std::vector<int>> adj(n);
	for (int i = 1; i < n; ++ i) {
		int u, v;
		std::cin >> u >> v;
		-- u, -- v;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}

	i64 ans = 0;
	std::vector<int> size(n);
	auto dfs = [&](auto && self, int u, int fa) -> void {
		size[u] = 1;
		for (auto & v : adj[u]) {
			if (v == fa) {
				continue;
			}

			self(self, v, u);
			if (n - size[v] >= k) {
				ans += size[v];
			}
			size[u] += size[v];
		}

		if (size[u] >= k) {
			ans += n - size[u];
		}
		ans += 1;
	};

	dfs(dfs, 0, -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;
}

G. Mukhammadali and the Smooth Array

题意:一个数组\(a\),你可以花费\(c_i\)\(a_i\)改成任何数。求让数组不递减的最小花费。

可以看作选一部分不操作,其它的操作的最小花费。
那么选出不操作的这一部分必须是不递减的。那么我们要让这一部分的\(c_i\)的和最大,这样另一部分的花费才会更小。
那么就是一个\(dp\)\(f_i = c_i + f_j(j <i, a_j \leq a_i)\)
这是典题,可以用树状数组优化为\(nlogn\)。维护一下前缀最大值就可以。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

template <class T>
struct Fenwick {
    int n;
    std::vector<T> tr;

    Fenwick(int _n) {
        init(_n);
    }

    void init(int _n) {
        n = _n;
        tr.assign(_n + 1, T{});
    }

    void add(int x, const T &v) {
        for (int i = x; i <= n; i += i & -i) {
            tr[i] = tr[i] + v;
        }
    }

    T query(int x) {
        T res{};
        for (int i = x; i; i -= i & -i) {
            res = res + tr[i];
        }
        return res;
    }

    T sum(int l, int r) {
        return query(r) - query(l - 1);
    }
};

struct Info {
	i64 max = 0;
};

Info operator + (const Info & a, const Info & b) {
	return {std::max(a.max, b.max)};
}

void solve() {
	int n;
	std::cin >> n;
	std::vector<int> a(n);
	for (int i = 0; i < n; ++ i) {
		std::cin >> a[i];
	}

	std::vector<int> c(n);
	for (int i = 0; i < n; ++ i) {
		std::cin >> c[i];
	}

	auto b = a;
	std::ranges::sort(b);
	b.erase(std::unique(b.begin(), b.end()), b.end());
	for (auto & x : a) {
		x = std::ranges::lower_bound(b, x) - b.begin() + 1;
	}

	int m = b.size();

	Fenwick<Info> tr(m + 1);
	for (int i = 0; i < n; ++ i) {
		tr.add(a[i], Info{tr.query(a[i]).max + c[i]});
	}

	std::cout << std::accumulate(c.begin(), c.end(), 0ll) - tr.query(m).max << "\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-10-29 00:50  maburb  阅读(516)  评论(0)    收藏  举报