洛谷P2664 树上游戏——点分治
原题链接
被点分治虐的心态爆炸了
题解
发现直接统计路径上的颜色数量很难,考虑转化一下统计方式。对于某一种颜色\(c\),它对一个点的贡献为从这个点出发且包含这种颜色的路径条数。
于是我们先点分一下,然后分别统计经过分治中心的路径对根和对其他点的贡献就行了。
推荐一篇比较详细的题解
代码:
#include <bits/stdc++.h>
using namespace std;
#define N 100000
#define pb push_back
#define ll long long
int n, c[N + 5];
vector<int> G[N + 5];
int root, S, sz[N + 5], vis[N + 5], maxsz[N + 5], col[N + 5], w[N + 5];
ll cnt[N + 5], ans[N + 5], sum1, sum2;
void getRoot(int u, int pa) {
sz[u] = 1; maxsz[u] = 0;
for (auto v : G[u]) {
if (v == pa || vis[v]) continue;
getRoot(v, u);
sz[u] += sz[v];
maxsz[u] = max(maxsz[u], sz[v]);
}
maxsz[u] = max(maxsz[u], S - sz[u]);
if (!root || maxsz[u] < maxsz[root]) root = u;
}
void dfs0(int u, int pa) {
sz[u] = 1;
for (auto v : G[u]) {
if (v == pa || vis[v]) continue;
dfs0(v, u);
sz[u] += sz[v];
}
}
void dfs1(int u, int pa) { // 计算w数组
col[c[u]]++;
w[u] = 0;
if (col[c[u]] == 1) w[u] = sz[u];
sum1 += w[u], cnt[c[u]] += w[u];
for (auto v : G[u]) {
if (v == pa || vis[v]) continue;
dfs1(v, u);
}
col[c[u]]--;
}
void dfs2(int u, int pa, int k) {
cnt[c[u]] += k * w[u];
sum1 += k * w[u];
for (auto v : G[u]) {
if (v == pa || vis[v]) continue;
dfs2(v, u, k);
}
}
void dfs3(int u, int pa) {
col[c[u]]++;
if (col[c[u]] == 1) sum2 += S - cnt[c[u]];
ans[u] += sum1 + sum2;
for (auto v : G[u]) {
if (v == pa || vis[v]) continue;
dfs3(v, u);
}
col[c[u]]--;
if (col[c[u]] == 0) sum2 -= S - cnt[c[u]];
}
void clear(int u, int pa) {
cnt[c[u]] = 0;
for (auto v : G[u]) {
if (v == pa || vis[v]) continue;
clear(v, u);
}
}
void calc(int u) {
dfs0(u, 0);
S = sz[u], sum1 = 0;
for (auto v : G[u]) {
if (vis[v]) continue;
dfs1(v, u);
}
ans[u] += S + sum1 - cnt[c[u]];
for (auto v : G[u]) {
if (vis[v]) continue;
dfs2(v, u, -1);
S -= sz[v];
col[c[u]]++;
sum2 = S - cnt[c[u]];
dfs3(v, u);
col[c[u]]--;
S += sz[v];
dfs2(v, u, +1);
}
clear(u, 0);
}
void solve(int u) {
vis[u] = 1;
calc(u);
for (auto v : G[u]) {
if (vis[v]) continue;
root = 0, S = sz[v], getRoot(v, u);
solve(root);
}
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%d", &c[i]);
for (int i = 1, x, y; i < n; ++i) {
scanf("%d%d", &x, &y);
G[x].pb(y), G[y].pb(x);
}
root = 0, S = n, getRoot(1, 0);
solve(root);
for (int i = 1; i <= n; ++i) printf("%lld\n", ans[i]);
return 0;
}
洛谷P2664 树上游戏——点分治的更多相关文章
- 洛谷P2664 树上游戏(点分治)
题意 题目链接 Sol 神仙题..Orz yyb 考虑点分治,那么每次我们只需要统计以当前点为\(LCA\)的点对之间的贡献以及\(LCA\)到所有点的贡献. 一个很神仙的思路是,对于任意两个点对的路 ...
- 洛谷 P2664 树上游戏 解题报告
P2664 树上游戏 题目描述 \(\text{lrb}\)有一棵树,树的每个节点有个颜色.给一个长度为\(n\)的颜色序列,定义\(s(i,j)\) 为 \(i\) 到 \(j\) 的颜色数量.以及 ...
- 洛谷P2664 树上游戏(点分治)
传送门 题解 因为一个sb错误调了一个晚上……鬼晓得我为什么$solve(rt)$会写成$solve(v)$啊!!!一个$O(logn)$被我硬生生写成$O(n)$了竟然还能过$5$个点……话说还一直 ...
- 洛谷P2664 树上游戏 【点分治 + 差分】
题目 lrb有一棵树,树的每个节点有个颜色.给一个长度为n的颜色序列,定义s(i,j) 为i 到j 的颜色数量.以及 现在他想让你求出所有的sum[i] 输入格式 第一行为一个整数n,表示树节点的数量 ...
- ●洛谷P2664 树上游戏
题链: https://www.luogu.org/problemnew/show/P2664题解: 扫描线,线段树维护区间覆盖 https://www.luogu.org/blog/ZJ75211/ ...
- 【刷题】洛谷 P2664 树上游戏
题目描述 lrb有一棵树,树的每个节点有个颜色.给一个长度为n的颜色序列,定义s(i,j) 为i 到j 的颜色数量.以及 \[sum_i=\sum_{j=1}^ns(i,j)\] 现在他想让你求出所有 ...
- 洛谷P2664 树上游戏
https://www.luogu.org/problemnew/show/P2664 #include<cstdio> #include<algorithm> #includ ...
- P2664 树上游戏
P2664 树上游戏 https://www.luogu.org/problemnew/show/P2664 分析: 点分治. 首先关于答案的统计转化成计算每个颜色的贡献. 1.计算从根出发的路径的答 ...
- Luogu P2664 树上游戏 dfs+树上统计
题目: P2664 树上游戏 分析: 本来是练习点分治的时候看到了这道题.无意中发现题解中有一种方法可以O(N)解决这道题,就去膜拜了一下. 这个方法是,假如对于某一种颜色,将所有这种颜色的点全部删去 ...
随机推荐
- 最新 优刻得java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.优刻得等10家互联网公司的校招Offer,因为某些自身原因最终选择了优刻得.6.7月主要是做系统复习.项目复盘.LeetCo ...
- Java核心1(第三章)
3.6字符串 子串substring(a,b)方法 第二个参数是不想复制的第一个位置 可以从一个较大的字符串中提取一个子串 3.6.2拼接 Java允许使用+号链接两个字符串 3.6.3不可 ...
- [百家号]7nm ARM 64核!华为Hi1620高性能CPU公开:3.0GHz
7nm ARM 64核!华为Hi1620高性能CPU公开:3.0GHz https://baijiahao.baidu.com/s?id=1617735663824201180&wfr=spi ...
- Linux中实用的命令
1. 查看linux机器是32位还是64位的方法: 1.file /sbin/init 或者file /bin/ls (注意命令中的空格) /sbin/init: ELF64- ...
- ecshop二次开发笔记
1. robots.txt 爬虫协议 网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取. 2. 入口文件 index.php 3. 目录结构分析 admin 后台 api 接口 ...
- Idea中maven的设置
File->setting 输入MAVEN 看到右侧设置情况 Maven home directory 熟路本地moven 仓库目录:D:/springboot/apach ...
- Go-常识补充-切片-map(类似字典)-字符串-指针-结构体
目录 Go 常识补充 Go 命名 打印变量类型科普 _ 关键字 命名规范相关 包目录规范 切片 多维切片 切片初始化的方法 多维切片初始化 切片删除元素(会略微影响效率 ,少用) copy 函数 打散 ...
- 怎样监听xhr.readyState值的变化
可以使用 xhr.onreadystatechange 属性指向的函数去监听 xhr.readyState 值的变化. 示例如下: var xhr = new XMLHttpRequest(); xh ...
- JS 验证字符串是否能转为json格式
var isJSON=function (str) { if (typeof str == 'string') { try { var obj = JSON.parse(str); if (typeo ...
- UVA10140PrimeDistance题解--质数/技巧
题目链接 https://www.luogu.org/problemnew/show/UVA10140 分析 \(L,R\)都很大,显然不能直接筛出\(L,R\)区间中的质数,这里需要一个结论 结论 ...