Luogu P2664 树上游戏 dfs+树上统计
题目:
分析:
本来是练习点分治的时候看到了这道题。无意中发现题解中有一种方法可以O(N)解决这道题,就去膜拜了一下。
这个方法是,假如对于某一种颜色,将所有这种颜色的点全部删去,原树会被割成若干棵小树,那么这个颜色对每个点的贡献就是:树的大小n - 所在小树的大小sz。所以我们要求出对于每个点来说,删去所有这个点颜色的点,这个点以下的小树size,这个用一个dfs和一个类似前缀和相减的过程,就可以求出。
接下来统计每个点的答案,就是所有颜色对这个点的贡献:n*颜色数-对于每种颜色这个点所处的小树size,这个用一遍dfs也可以求出来,类似容斥的思想。
代码中有注释:
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=;
struct node{int y,nxt;}e[N*];
ll n,sm,qwq,vis[N],ans[N],c=,h[N];
ll col[N],siz[N],tmp[N],lz[N],sn[N];
void add(int x,int y){
e[++c]=(node){y,h[x]};h[x]=c;
e[++c]=(node){x,h[y]};h[y]=c;
} void dfs(int x,int fa){
siz[x]=;ll cnt=tmp[col[fa]];
for(int i=h[x],y;i;i=e[i].nxt)
if((y=e[i].y)!=fa) dfs(y,x),siz[x]+=siz[y];
tmp[col[x]]++;if(fa){
lz[x]=siz[x]-tmp[col[fa]]+cnt;
tmp[col[fa]]+=lz[x];
} return ;
} void get(int x,int fa){
ll sgn=sn[col[fa]];
qwq+=lz[x]-sn[col[fa]];
sn[col[fa]]=lz[x];
ans[x]=n*sm-qwq+sn[col[x]];
for(int i=h[x],y;i;i=e[i].nxt)
if((y=e[i].y)!=fa) get(y,x);
sn[col[fa]]=sgn;
qwq-=lz[x]-sn[col[fa]];
} int main(){
scanf("%lld",&n);
for(int i=;i<=n;i++){
scanf("%lld",&col[i]);
if(!vis[col[i]])
vis[col[i]]=,sm++;
} for(int i=,x,y;i<n;i++)
scanf("%d%d",&x,&y),add(x,y);
dfs(,);
for(int i=;i<=;i++)
if(vis[i]) qwq+=n-tmp[i],
sn[i]=n-tmp[i];get(,);
for(int i=;i<=n;i++)
printf("%lld\n",ans[i]);return ;
}//lz[x]表示将x的父节点这种颜色的点全部删掉余下的这个
//小树的size
//sn记录的是对于每种颜色,当前深度以上的最近的小树sz
//qwq变量计算的是当前位置对于每种颜色所处的小树sz总和
dfs+树上统计
Luogu P2664 树上游戏 dfs+树上统计的更多相关文章
- Luogu P1278 单词游戏(dfs)
P1278 单词游戏 题意 题目描述 \(Io\)和\(Ao\)在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何 ...
- 洛谷 P2664 树上游戏 解题报告
P2664 树上游戏 题目描述 \(\text{lrb}\)有一棵树,树的每个节点有个颜色.给一个长度为\(n\)的颜色序列,定义\(s(i,j)\) 为 \(i\) 到 \(j\) 的颜色数量.以及 ...
- P2664 树上游戏
P2664 树上游戏 https://www.luogu.org/problemnew/show/P2664 分析: 点分治. 首先关于答案的统计转化成计算每个颜色的贡献. 1.计算从根出发的路径的答 ...
- 【Luogu2664】树上游戏(点分治)
[Luogu2664]树上游戏(点分治) 题面 洛谷 题解 很好的一道点分治题. 首先直接点分治,考虑过每个分治重心的链的贡献. 我们从分治重心开始找每种颜色,强制令一种颜色只在其到分治重心的链上第一 ...
- LG2664 树上游戏
树上游戏 题目描述 lrb有一棵树,树的每个节点有个颜色.给一个长度为n的颜色序列,定义s(i,j) 为i 到j 的颜色数量.以及 $$sum_i=\sum_{j=1}^ns(i,j)$$ 现在他想让 ...
- Luogu P2680 运输计划(二分+树上差分)
P2680 运输计划 题意 题目背景 公元\(2044\)年,人类进入了宇宙纪元. 题目描述 公元\(2044\)年,人类进入了宇宙纪元. \(L\)国有\(n\)个星球,还有\(n-1\)条双向航道 ...
- BZOJ_4238_电压_树上差分+dfs树
BZOJ_4238_电压_树上差分+dfs树 Description 你知道Just Odd Inventions社吗?这个公司的业务是“只不过是奇妙的发明(Just Odd Inventions)” ...
- 【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询
题目描述 给出一棵n个节点的树,每一个节点开始有一个互不相同的颜色,初始根节点为1. 定义一次感染为:将指定的一个节点到根的链上的所有节点染成一种新的颜色,代价为这条链上不同颜色的数目. 现有m次操作 ...
- [luogu]P1070 道路游戏[DP]
[luogu]P1070 道路游戏 题目描述小新正在玩一个简单的电脑游戏.游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针 ...
随机推荐
- [Xcode 实际操作]九、实用进阶-(15)屏幕截屏:截取当前屏幕上的显示内容
目录:[Swift]Xcode实际操作 本文将演示如何截取屏幕画面,并将截取图片,存入系统相册. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UI ...
- css 三种引用方式
内联式 代码 <!doctype html> <html lang="en"> <head> <meta charset="UT ...
- C 语言实例 - 字符串复制
C 语言实例 - 字符串复制 C 语言实例 C 语言实例 将一个变量的字符串复制到另外一个变量中. 实例 - 使用 strcpy() #include <stdio.h> #include ...
- Markdown - 如何使用上标、下标
解决方法 Markdown可以和HTML的语法兼容,可以通过HTML的上标和下标标签来实现效果: 标签 写法 效果 上标 2<sup>10</sup> 210 下标 H< ...
- JSP | 基础 | 连接数据库
package util; import java.sql.DriverManager; import java.sql.SQLException; import com.mysql.jdbc.*; ...
- STP-3-收敛到新的STP拓扑
事实上,即使拓扑已经稳定,STP也从未停止工作,对每个收到的BPDU,交换机都会重新计算自己对于根桥,RP,DP的选择.在稳定的拓扑中,交换机收到的BPDU不变,因此对这些BPDU的处理会一遍一遍产生 ...
- laravel之null替换空字符串中间件
在laravel写接口的时候免不了数据库中保存null,可用诸如设置ORM的访问器或以下方法处理 $goods->name?$goods->name:''; 其实可以利用路由中间件,在需要 ...
- Codeforces 1142C(转化、凸包)
可以变换坐标:x' = x, y' = y - x ^ 2,如此之后可得线性函数x' * b + c = y',可以发现两点连边为抛物线,而其他点都在这条线下方才满足题意,故而求一个上凸壳即可. #i ...
- 17 文件和网络I/O
1 文件和网络I/O 1.1 文件处理 groovy向java所提供的File 类,新增了几个方便的方法.分别是:eachLine和.text. package file class F ...
- 转 oradebug命令详解
转 http://blog.itpub.net/28883355/viewspace-1080879/ oradebug它可以启动跟踪任何会话,dump SGA和其它内存结构,唤醒ORACLE进程,如 ...