AtCoder Beginner Contest 348
E - Minimize Sum of Distances
- 给定一颗
个节点的树和长度为 的序列 。设 ,求 。其中 表示树上 的简单路径上边的数量。 , 。
令
显然可以轻易地求出
如果
由于在题目中
然后像这样类似 DP 地转移即可。
int n, u, v, w[N];
int h[N], e[N], ne[N], idx;
int res, sum;
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
int dep[N], S;
int F[N];
void dfs(int u, int f) {
dep[u] = dep[f] + 1;
sum += (dep[u] - 1) * w[u];
F[u] = w[u];
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (v == f) continue;
dfs(v, u);
F[u] += F[v];
}
return;
}
void dfs2(int u, int f) {
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (v == f) continue;
sum -= F[v];
sum += S - F[v];
res = min(res, sum);
dfs2(v, u);
sum -= S - F[v];
sum += F[v];
}
return;
}
void solve() {
memset(h, -1, sizeof h);
fin >> n;
for (int i = 1; i < n; ++ i ) {
fin >> u >> v;
add(u, v), add(v, u);
}
for (int i = 1; i <= n; ++ i ) fin >> w[i], S += w[i];
dfs(1, 0);
res = sum;
dfs2(1, 0);
fout << res;
}
F - Oddly Similar
- 有
个长度为 的序列 。如果两个序列 满足有奇数个 满足 ,那么 就是相似的。求有多少对 满足 且 和 是相似的。 , 。
直接暴力是
不难发现这个复杂度除以
bitset 最后再用。先考虑怎么将数据用 bool 数组存储。
定义 bool 型的
考虑计算行
那么类似于暴力,我们需要枚举列
代码是这样的:
const int N = 2001, M = 1000;
bool cnt[N][M][N], f[N];
for (int i = 1; i <= n; ++ i )
for (int j = 1; j <= m; ++ j )
cnt[j][a[i][j]][i] = 1;
for (int i = 1; i <= n; ++ i ) {
for (int j = 1; j <= n; ++ j ) f[j] = 0;
for (int j = 1; j <= m; ++ j )
for (int k = 1; k <= n; ++ k ) {
f[k] ^= cnt[j][a[i][j]][k];
// 原写法是:if (cnt[j][a[i][j]][k]) f[k] ^= 1;
}
f[i] = 0; // 显然自己和自己不能构成答案
for (int j = 1; j <= n; ++ j ) res += f[j];
}
printf("%d\n", res / 2);
这样的复杂度还是
那么中间 for (int k = 1; k <= n; ++ k ) f[k] ^= cnt[j][a[i][j]][k];
就可以改为 f ^= cnt[j][a[i][j]];
了。总复杂度降低为
#include <bits/stdc++.h>
using namespace std;
const int N = 2001, M = 1000;
int n, m, a[N][N], res;
bitset<N> cnt[N][M], f;
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++ i )
for (int j = 1; j <= m; ++ j ) {
scanf("%d", &a[i][j]);
cnt[j][a[i][j]][i] = 1;
}
for (int i = 1; i <= n; ++ i ) {
f.reset();
for (int j = 1; j <= m; ++ j ) f ^= cnt[j][a[i][j]];
f[i] = 0; // 显然自己和自己不能构成答案
res += f.count();
}
printf("%d\n", res / 2);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下