VP Educational Codeforces Round 19
A. k-Factorization
题意:选
我们前面让每个数越小越好,然后让最后一个数补上就行,这样能凑出来最多的数。那么就直接分解质因子,这样能安排最多的数。
点击查看代码
void solve() {
int n, k;
std::cin >> n >> k;
std::vector<int> a;
for (int i = 2; i * i <= n && a.size() + 1 < k; ++ i) {
if (n % i == 0) {
while (n % i == 0 && a.size() + 1 < k) {
a.push_back(i);
n /= i;
}
}
}
if (a.size() < k && n > 1) {
a.push_back(n);
}
if (a.size() < k) {
std::cout << -1 << "\n";
} else {
for (int i = 0; i < k; ++ i) {
std::cout << a[i] << " \n"[i == k - 1];
}
}
}
B. Odd sum
题意:找数组的一个子序列,使得和是奇数,并且和最大。
要使得和是奇数,发现和拿多少偶数没关系,我们只需要保证拿奇数个奇数就行。那么偶数大于0的都拿上。然后奇数从大到小排序,取奇数位置前缀和的最大值。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a, b;
for (int i = 0; i < n; ++ i) {
int x;
std::cin >> x;
if (x % 2 == 0) {
b.push_back(x);
} else {
a.push_back(x);
}
}
std::sort(a.begin(), a.end(), std::greater<int>());
std::sort(b.begin(), b.end(), std::greater<int>());
i64 ans = 0;
for (auto & x : b) {
if (x > 0) {
ans += x;
}
}
i64 sum = -1e18, pre = 0;
for (int i = 0; i < a.size(); ++ i) {
pre += a[i];
if (i % 2 == 0) {
sum = std::max(sum, pre);
}
}
std::cout << ans + sum << "\n";
}
C. Minimal string
题意:你有一个字符
点击查看代码
void solve() {
std::string s;
std::cin >> s;
int n = s.size();
std::string t;
std::vector<int> suf(n + 1, 30);
for (int i = n - 1; i >= 0; -- i) {
suf[i] = std::min(s[i] - 'a', suf[i + 1]);
}
std::string ans;
for (int i = 0; i < n; ++ i) {
while (t.size() && t.back() - 'a' <= suf[i]) {
ans += t.back();
t.pop_back();
}
if (s[i] - 'a' <= suf[i]) {
ans += s[i];
} else {
t += s[i];
}
}
while (t.size()) {
ans += t.back();
t.pop_back();
}
std::cout << ans << "\n";
}
D. Broken BST
题意:给你一棵普通二叉树,如果把它当成二叉搜索树来用,节点的值中有多少不能被搜索到。
这题坑点就是,是问有多少值不能被搜到,而不是有多少节点。所以如果一个值出现在多个节点,只要有一个节点能被搜到这个值就能被搜到。
考虑每个节点什么时候能被搜到,发现搜索下来就是一条路径,如果这个路径往左拐一次,那么该节点的值就要小于这个点的值,如果右拐一次,那么值就要大于这个点的值,发现最后到该节点是就形成了一个取值区间,如果这个点的权值在这个区间就能被取到,那么我们就这样dfs遍历一遍树就可以求出答案。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> v(n + 1), l(n + 1), r(n + 1);
std::vector<int> in(n + 1);
for (int i = 1; i <= n; ++ i) {
std::cin >> v[i] >> l[i] >> r[i];
if (l[i] != -1) {
++ in[l[i]];
}
if (r[i] != -1) {
++ in[r[i]];
}
}
std::map<int, int> mp;
auto dfs = [&](auto self, int u, int min, int max) -> void {
if (min < v[u] && v[u] < max) {
mp[v[u]] = 1;
}
if (l[u] != -1) {
self(self, l[u], min, std::min(max, v[u]));
}
if (r[u] != -1) {
self(self, r[u], std::max(min, v[u]), max);
}
};
int root = 0;
for (int i = 1; i <= n; ++ i) {
if (in[i] == 0) {
root = i;
}
}
dfs(dfs, root, -1e9, 1e9);
int ans = 0;
for (int i = 1; i <= n; ++ i) {
ans += mp[v[i]];
}
std::cout << n - ans << "\n";
}
E. Array Queries
题意:一个长度为
这几天碰到了好几道根号分治题。
总长度只有
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n + 1);
for (int i = 1; i <= n; ++ i) {
std::cin >> a[i];
}
int m = std::sqrt(n);
std::vector f(n + 1, std::vector<int>(m + 1));
for (int i = n; i >= 1; -- i) {
for (int j = 1; j <= m; ++ j) {
f[i][j] = i + j + a[i] > n ? 1 : f[i + j + a[i]][j] + 1;
}
}
int q;
std::cin >> q;
while (q -- ) {
int p, k;
std::cin >> p >> k;
if (k <= m) {
std::cout << f[p][k] << "\n";
} else {
int ans = 0;
while (p <= n) {
p = p + a[p] + k;
++ ans;
}
std::cout << ans << "\n";
}
}
}
F. Mice and Holes
题意:坐标上有一些老鼠和一些洞,每个洞有容量限制
开始以为是网络流,但内存只给了256M, 直接
考虑
点击查看代码
f[0][0] = 0;
for (int j = 1; j <= m; ++ j) {
for (int i = 0; i <= n; ++ i) {
for (int k = std::max(0, i - b[j].second); k <= i; ++ k) {
f[i][j] = std::min(f[i][j], f[k][j - 1] + sum[i][j] - sum[k][j]);
}
}
}
但这个是
注意内存卡的很死,需要用滚动数组优化。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<int> a(n + 1);
std::vector<std::pair<int, int>> b(m + 1);
for (int i = 1; i <= n; ++ i) {
std::cin >> a[i];
}
for (int i = 1; i <= m; ++ i) {
std::cin >> b[i].first >> b[i].second;
}
std::sort(a.begin() + 1, a.end());
std::sort(b.begin() + 1, b.end());
const i64 inf = 1e18;
std::vector<i64> f(n + 1, inf);
std::vector<i64> sum(n + 1);
f[0] = 0;
std::vector<int> q(n + 10);
for (int j = 1; j <= m; ++ j) {
std::vector<i64> g(n + 1, inf);
for (int i = 1; i <= n; ++ i) {
sum[i] = sum[i - 1] + std::abs(a[i] - b[j].first);
}
int hh = 0, tt = -1;
for (int i = 0; i <= n; ++ i) {
while (hh <= tt && q[hh] < i - b[j].second) {
++ hh;
}
while (hh <= tt && f[q[tt]] - sum[q[tt]] >= f[i] - sum[i]) {
-- tt;
}
q[ ++ tt] = i;
g[i] = f[q[hh]] + sum[i] - sum[q[hh]];
}
f = g;
}
i64 ans = f[n] == inf ? -1 : f[n];
std::cout << ans << "\n";
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!