P5593 题解

news/2025/11/6 10:52:53/文章来源:https://www.cnblogs.com/FRZ29/p/18448657

题目

分析

首先考虑什么样的颜色能被链覆盖。

容易想到当某种颜色恰巧在一条链上会被覆盖。

所以只需要判断一种颜色是否能构成链即可,链的贡献也很好计算。

算法

考虑链的性质:有且仅有两个端点。

凭借这个性质,可以判断一种颜色是否在一条链上。

在 dfs 中考虑各种情况。

假设一个点 \(u\),其颜色为 \(c\),有以下 \(2\) 种情况判断 \(u\) 是否为端点。

  1. 如果 \(u\) 的子树中没有颜色 \(c\) 的节点,那么 \(u\) 点是一个端点。
  2. 满足两个条件。
    1. 除了 \(u\) 的子树没有颜色 \(c\) 的节点。
    2. \(u\) 的所有儿子中,只有一个儿子的子树中有颜色 \(c\)

判断端点数量是否等于 \(2\),等于 \(2\) 说明该种颜色恰好构成一条链。

还有一个特殊情况:某个颜色可能只有一个点,需要直接算答案。

如果是一条链的话,假设两条节点为 \(p, q\),对答案的贡献有两种情况。

  1. 如果 \(p, q\) 均是满足上述第 \(1\) 种情况的,答案为 \(sz_p \times sz_q\)
  2. 如果 \(p\) 是满足上述第 \(2\) 种情况的,考虑一下,因为 \(p\) 的所有儿子中,只有一个儿子的子树中有颜色 \(c\),假设该儿子为 \(pos\),所以 \(p\) 的其他儿子的子树中的节点也能对答案有贡献,故答案为 \((n - sz_{pos}) \times sz_q\)

如何实现见代码。

#ifdef ONLINE_JUDGE
#else
#define FRZ_29
#endif#include <iostream>
#include <cstdio>
typedef long long LL;using namespace std;void RD() {}
template<typename T, typename... U> void RD(T&x, U&... arg) {x = 0; int f = 1; char ch = getchar();while (ch > '9' || ch < '0') { if (ch == '-') ch = getchar(); ch = getchar(); }while (ch <= '9' && ch >= '0') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();x *= f; RD(arg...);
}void WT() {}
template<typename T> void WT(T x) {if (x < 0) { putchar('-'); x = -x; }if (x > 9) WT(x / 10);putchar(x % 10 + '0');
}const int N = 3e6 + 5;#define LF(i, __l, __r) for (int i = __l; i <= __r; i++)
#define RF(i, __r, __l) for (int i = __r; i >= __l; i--)int head[N], ver[N << 1], Next[N << 1], _tot = 1;
int n, a[N], tot[N], nos[N], enos[N], cnt[N], sz[N];
LL ans, ans1[N], ans2[N];void add(int u, int v) {ver[++_tot] = v;Next[_tot] = head[u], head[u] = _tot;
}/*
如果 flag == 1,才能判断为端点
这是由 flag 的增加方式决定的
*/
void dfs(int u, int _f) {int c = a[u], flag = 0, pos = 0;int k = cnt[c];sz[u] = 1;for (int i = head[u]; i; i = Next[i]) {int v = ver[i];if (v == _f) continue;int la = cnt[c];dfs(v, u);ans1[u] += 1LL * sz[u] *sz[v];sz[u] = sz[u] + sz[v];if (la != cnt[c]) flag++, pos = v; // 与判断是否为端点的条件2相关}                                      // 如果该条件被满足两次pos自然就无用了ans1[u] += 1LL * sz[u] * (n - sz[u]);if (k || cnt[c] != tot[c] - 1) flag++; // 与判断是否为端点的条件1相关cnt[c]++;if (flag == 1) {if (!enos[c]) nos[c] = u;else {int p = pos ? n - sz[pos] : sz[u];ans2[c] = 1LL * p * sz[nos[c]];}enos[c]++;}
}int main() {
#ifdef FRZ_29freopen("read.in", "r", stdin);freopen("out.out", "w", stdout);
#endifRD(n);LF(i, 1, n) {RD(a[i]); tot[a[i]]++; nos[a[i]] = i;}LF(i, 1, n - 1) {int u, v; RD(u, v);add(u, v), add(v, u);}dfs(1, 0);LF(i, 1, n) {if (tot[i] == 0) ans ^= 1LL * n * (n - 1) / 2;else if (tot[i] == 1) ans ^= ans1[nos[i]];else if (enos[i] == 2) ans ^= ans2[i];else ans ^= 0;}WT(ans);return 0;
}

七月流火,九月授衣。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/808774.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AtCoder Beginner Contest 374

写的迷迷糊糊的省流版A. 判断末三位即可 B. 逐位判断即可 C. 枚举所有分组情况即可 D. 枚举线段顺序、端点顺序即可 E. 二分答案,发现贵的机器数量不超过\(100\),枚举求最小花费看是否可行即可 F. 朴素DP,复杂度分析得到有效时刻不超过\(O(n^2)\)而非\(O(s_i)\),直接\(DP\)…

2024年10月5日

今天刚刚送走了我的兄弟,心理略有点失落,天下没有不散的宴席,有缘再会

9月30日小测知识汇总

在今天的小测试中需要完成GUI 显示30道四则运算算术题,并且加上计时功能,在测试结束后整理所学知识时有以下几点自己不掌握的知识点: 1:思维流程:1初始化全局变量 数据存储结构,开始时间和结束时间,运算符,正确率计数器,题目数量;2构造方法,JFrame窗口初始化以及Butt…

一个需求 正确打开实际为图片(.jpg .heic),但是被后缀命名为其它类型(.pdf .html)的图片

irfanview错误地打开了.html为一些乱码文字的html,但是实际是图片。 jpegview可以 .pdf格式的图片 这俩都没问题 (关于为什么要 后缀命名为其它类型 ,因为我要在缩略图中区分某些特殊图片。

问题们

这一周打了两场模拟赛,考试的题目都十分恶心。 T1 T2都能补,T3 T4基本上没啥希望。 这周有疑问的题目:梦熊模拟赛T2 dp的变态应用奇怪的线段树题目奇怪的线段树题目梦熊X组T2,赛时放弃

三千字长文:我知道的输入法技巧都在这了

这些技巧能让你打字更快、更好。这些技巧能让你打字更快、更好。 ‍ 官方设置 目前市面上有很多输入法软件,其中很多功能都是共有的,因为都是基础功能。因此,当选择了一款输入法好,可以先打开设置页面,好好地了解有什么功能。 此外,还可以看输入法官网文档,例如搜狗输入…

通过图片中信息得出地点

图片中会隐藏信息,比如右下角的小票将它翻转,可以看到 erbang Alaf Restaurant,Bangunan,Jalan SS21/39,Selang,这些字眼,于是直接用浏览器搜索 Gerbang正好填补了没看到的缺角, 地址上的Bangunan,Jalan SS21/39符合小票上的字,说明这就是图中的餐厅 作者想说,当要发布照…

实验1:UML与面向对象程序设计原则

[实验任务一]:UML复习 阅读教材第一章复习UML,回答下述问题: 面向对象程序设计中类与类的关系都有哪几种?分别用类图实例说明。 1、关联关系2、聚合关系3、依赖关系4、组合关系[实验任务二]:单一职责原则 登录模块在实际项目开发中很常见,请按照教材28页(PPT49页)利用单…