首页 > 其他分享 >dus on tree学习笔记

dus on tree学习笔记

时间:2023-08-11 09:04:10浏览次数:31  
标签:子树 暴力 int tree 笔记 dus 节点

前言

dus on tree 就像其实就像是暴力,但是通过选择正确的顺序,使得暴力变得更加的快速。

算法思路

查看题目

给出一颗 n 个节点的树,每个节点有一个颜色,询问你没个节点的子树中有多少中颜色。

显然,我们知道暴力扫的话是枚举每个点,再暴力去找他的子树,显然在暴力的情况下是 \(O(n^2)\) 的。但我们发现,其实很多信息我们都会重复用到,如果每次都删除过于浪费,但如果直接保存的话又可能会影响到其他的子树。

所以我们要找到一个正确的顺序去保存,显然,我们可以在之后所有的节点都包括这颗子树的时候,就可以保存答案了。什么时候都保存呢?我们可以规定一个枚举顺序,规定某一条边必需最后访问,这样从上面递归到这条最后的边的时候,前面的边肯定都已经递归完了,所以我们就可以保存这颗子树的所有信息了。

我们发现这样最后最后一条边所在的子树会被访问1次,其他的会被访问2次,显然希望最后一条边所在的子树越大越好,所以就可以规定重边为最后一条边。

code


#include<bits/stdc++.h>
using namespace std;
const int N=100011;
int n;
int col[N];
struct node{
	int to,lt;
}e[N<<1];
int tot,last[N];
void add(int u,int v){
	e[++tot].lt=last[u];
	e[tot].to=v;
	last[u]=tot;
}
int sum;
int size[N],son[N],L[N],R[N],cnt,id[N];
void dfs1(int u,int fa){//找轻重边,dfs序 
	size[u]=1;
	L[u]=++cnt;
	id[cnt]=u;
	for(int i=last[u];i;i=e[i].lt){
		int v=e[i].to;
		if(v==fa)continue;
		dfs1(v,u);
		size[u]+=size[v];
		if(size[son[u]]<size[v])son[u]=v;
	}
	R[u]=cnt;
}
int a[N],ans[N];
void add(int u){//加减儿子,发没发现很想莫队
	a[col[u]]++;
	if(a[col[u]]==1)sum++;
}
void del(int u){//所以这玩意还有个名字叫子树莫队 
	a[col[u]]--;
	if(a[col[u]]==0)sum--;
}
void dfs2(int u,int fa,bool keep){//keep表示这条边要不要存 
	for(int i=last[u];i;i=e[i].lt){//先把亲儿子求完 
		int v=e[i].to;
		if(v==fa||v==son[u])continue;
		dfs2(v,u,false);
	}
	if(son[u])dfs2(son[u],u,true);//重儿子是要保存的 
	for(int i=last[u];i;i=e[i].lt){
		int v=e[i].to;
		if(v==fa||v==son[u])continue;
		for(int j=L[v];j<=R[v];j++)add(id[j]);
	}
	add(u);
	ans[u]=sum;
	if(keep==false){
		//注意是要把整颗子树的信息都删掉 
		for(int i=L[u];i<=R[u];i++)del(id[i]);
	}
	return ;
}
int m;
int main(){
	cin>>n;
	for(int i=1;i<=n-1;i++){
		int u,v;
		cin>>u>>v;
		add(u,v);
		add(v,u);
	}
	for(int i=1;i<=n;i++)cin>>col[i];
	dfs1(1,0);
	dfs2(1,1,false);
	cin>>m;
	for(int i=1;i<=m;i++){
		int k;
		cin>>k;
		cout<<ans[k]<<endl;
	}
}

标签:子树,暴力,int,tree,笔记,dus,节点
From: https://www.cnblogs.com/shadom/p/17622111.html

相关文章

  • Programming abstractions in C阅读笔记:p91-p106
    《ProgrammingAbstractionsInC》学习第45天,p91-p102,完成第二章内容学习。总结如下:一、技术总结1.垃圾回收p91,"Somelanguage,includingJavasupportasystemfordynamicallocationthatactivelygoesthroughtoseewhatpartsofitareused,freeinganystorageth......
  • [刷题笔记] [JSOI2010] 连通数
    DescriptionProblem由于题目太短我直接上图罢Analysis题目描述非常简单,但是直接爆搜肯定会TLE,毕竟\(n\leq2000\)并且timelimit=300ms。我们发现如果题目保证无环直接topsort即可,问题就在环上,如何处理环呢?我们可以缩点,缩点笔记,显然我们只需要统计答案数,缩完点后就变成了......
  • 《深入理解Java虚拟机》读书笔记:垃圾收集算法
    由于垃圾收集算法的实现涉及大量的程序细节,而且各个平台的虚拟机操作内存的方法又各不相同,因此本节不打算过多地讨论算法的实现,只是介绍几种算法的思想及其发展过程。垃圾收集算法概要 1、标记-清除算法标记-清除算法最基础的收集算法是“标记-清除”(Mark-Sweep)算法,算法分......
  • Paper Reading: NBDT: Neural-Backed Decision Trees
    目录研究动机文章贡献本文方法推理建立层次结构用WordNet标记决策节点微调和树监督损失实验结果对比实验结果可解释性识别错误的模型预测引导图像分类人更倾向的解释识别有缺陷的数据标签优点和创新点PaperReading是从个人角度进行的一些总结分享,受到个人关注点的侧重和实力......
  • GAMES101笔记(04)
    本篇对应的是第七课上节课讲完了光栅化的内容,这节课讲的有深度测试,光照和着色深度测试我在学校看shader入门精要的时候有些印象,但也仅此而已了,我觉得还是要先补一下图形学的知识再去啃入门精要会好一些 深度缓存在计算机成像时,对于一个我们要输出的画面,如何确保画面上的东......
  • 「学习笔记」并查集
    真的有必要说吗?直接上封装好的模板吧,包含路径压缩和按秩合并。structunion_find_set{intfa[N],siz[N];int&operator[](constint&x){returnfa[x];}voidreset(){for(inti=1;i<=n;++i){fa[i]=i;......
  • 「学习笔记」随机数据
    前置知识——随机函数我们日常用的随机函数为rand(),虽然比较慢,但已经足够用了,它会随机生成一个范围在\([0,2^{31}-1]\)中的一个数。使用时要用随机种子seed,可以使用srand(seed)来设置、更改随机种子,当然,不初始化也是可以的,只是同一个程序用相同的seed、相同的机器、相......
  • Atcoder杂题笔记
    大概会把博客当草稿纸用(当然写出正解还是会把正解贴出来。[ARC080E]YoungMaids(待补代码)给定正偶数\(N\)。给定\(N\)元排列\(p=(p_1,p_2,...,p_N)\).Snuke打算根据下述步骤构造一个\(N\)元排列\(q\)。首先,令\(q\)为空。接下来,执行下述操作直到\(p\)为空......
  • openGauss学习笔记-36 openGauss 高级数据管理-TRUNCATE TABLE语句
    openGauss学习笔记-36openGauss高级数据管理-TRUNCATETABLE语句清理表数据,TRUNCATETABLE用于删除表的数据,但不删除表结构。也可以用DROPTABLE删除表,但是这个命令会连表的结构一起删除,如果想插入数据,需要重新建立这张表。它和在目标表上进行无条件的DELETE有同样的效果,但由于......
  • 全局引用ant-design-vue的TreeSelect没有样式
    在全局只按需引用了TreeSelect---vue.use(TreeSelect)没有样式.........需要在babel.config.js里的plugins配置plugins:[["import",{"libraryName":"ant-design-vue",//库名称"libraryDirectory"......