Ethflow Round 1 (Codeforces Round 1001, Div. 1 + Div. 2)
A. String
题意:给你一个01串,你每次选一个子序列,其中相邻的两位不相同,如何把这个子序列位置上的数取反,问多少次能变成全0。
因为必须是10交替,那么取反后相当于没操作。所以我们每次操作一个1就行。这样操作数是1的个数。
点击查看代码
void solve() {
std::string s;
std::cin >> s;
std::cout << std::count(s.begin(), s.end(), '1') << "\n";
}
B. Clockwork
题意:有
因为我们不让任何一个时钟变为0,那么我们肯定是要走遍每一个位置。对于第
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
for (int i = 0; i < n; ++ i) {
if (i * 2 >= a[i] || (n - 1 - i) * 2 >= a[i]) {
std::cout << "NO\n";
return;
}
}
std::cout << "YES\n";
}
C. Cirno and Operations
题意:一个数组,每次可以让它变成它的差分数组或者把它翻转。你可以操作任意次。问可以得到的最大数组和是多少。
数组总和的原值为
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<i64> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
i64 ans = std::accumulate(a.begin(), a.end(), 0ll);
for (int i = 0; i + 1 < n; ++ i) {
if (a[0] < a.back()) {
std::reverse(a.begin(), a.end());
}
i64 sum = 0;
for (int i = 0; i + 1 < a.size(); ++ i) {
a[i] = a[i] - a[i + 1];
sum += a[i];
}
ans = std::max(ans, sum);
a.pop_back();
}
std::cout << ans << "\n";
}
D. Balanced Tree
题意:给你一棵树,每个点有一个取值范围,你每次可以让一棵子树上的点都加一。要让所有节点值相同,问这个值最小是多少。
考虑一棵子树,我们假设值已经取好了,那么我们可以先让值比根节点小子节点的都变成根节点的值,然后这棵子树就只剩下了大于等于根节点的子节点,接下来如何操作?这里我举一个例子(数字代表值):
怎样让这棵树的答案最小?模拟发现,我们应该先让1变成2,然后把这两个2变成4,最后全部变成7.
发现就是每次操作第二小的值,一直操作到最小值等于它。设
那么我们也可以假定1节点为根,然后进行树形dp。叶子节点的取值肯定是
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> l(n), r(n);
for (int i = 0; i < n; ++ i) {
std::cin >> l[i] >> r[i];
}
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);
}
std::vector<int> f(n);
i64 ans = 0;
auto dfs = [&](auto self, int u, int fa) -> void {
int max = 0;
for (auto & v : adj[u]) {
if (v == fa) {
continue;
}
self(self, v, u);
max = std::max(max, f[v]);
}
if (r[u] >= max) {
f[u] = std::max(max, l[u]);
} else {
for (auto & v : adj[u]) {
if (v == fa) {
continue;
}
ans += std::max(0, f[v] - r[u]);
}
f[u] = r[u];
}
};
dfs(dfs, 0, -1);
ans += f[0];
std::cout << ans << "\n";
}
E1. The Game (Easy Version)
题意:两个人在树上玩游戏,每个点有点权。一开始第一个人选一个点
//我也不知道我的做法会不会被hack,感觉可能tle。不过最终还是过了
我们发现,好像可以选次大值,这样另一个人只能选最大值,那么我们就赢了。但这样是错的,因为可以所有大于我们选的这个点点权的点都在这个点的子树下,那么就会被我们一起删了,导致下一个人无点可选。但这启发我们,如果存在一个点权为
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
std::vector<std::vector<int> > w(n + 1);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
w[a[i]].push_back(i);
}
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);
}
std::vector<int> b;
for (int i = n; i >= 1; -- i) {
if (!w[i].empty()) {
b.push_back(i);
}
}
std::vector<int> d(n), size(n);
auto dfs = [&](auto self, int u, int fa) -> void {
size[u] = 1;
for (auto & v : adj[u]) {
if (v == fa) {
continue;
}
d[v] = d[u] + 1;
self(self, v, u);
size[u] += size[v];
}
};
dfs(dfs, 0, -1);
std::vector<int> st(n);
int W;
auto dfs1 = [&](auto self, int u) -> int {
if (st[u]) {
return size[u];
}
int sum = a[u] > W;
for (auto & v : adj[u]) {
if (d[v] != d[u] + 1) {
continue;
}
sum += self(self, v);
}
if (sum == size[u]) {
st[u] = 1;
}
return sum;
};
int sum = w[b[0]].size();
for (int i = 1; i < b.size(); ++ i) {
W = b[i];
std::sort(w[b[i]].begin(), w[b[i]].end(), [&](int i, int j) {
return d[i] > d[j];
});
for (auto & x : w[b[i]]) {
if (dfs1(dfs1, x) != sum) {
std::cout << x + 1 << "\n";
return;
}
}
sum += w[b[i]].size();
}
std::cout << 0 << "\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框架的用法!