首页 > 其他分享 >2023.9.3 hpz's problems about trees

2023.9.3 hpz's problems about trees

时间:2023-09-03 20:46:27浏览次数:52  
标签:hpz 连通 颜色 int siz problems vec cs 2023.9

P2664 树上游戏

对于颜色 \(c\),如果我们把颜色 \(c\) 的点全部都删除,那么我们会得到若干个连通块。
连通块里面的路径是没有贡献的,连通块联通外面的路径都会有这个颜色做了贡献。
对于一个连通块,其里面所有点都能有 \(n-siz(连通块)\) 的贡献。
如果我们每次枚举颜色,再计算连通块,这样是 \(O(n^2)\).
那么我们考虑一次把所有颜色计算出来。

若当前 dfs 到一个 \(u\),其颜色是 \(c\),那么删除它,其所有儿子 \(v_1,v_2,...\) 都会各自形成一个连通块。
遍历其儿子。我们现在要求出这个儿子 \(v\) 所在连通块的大小。
如何求呢?这个连通块的大小是 \(v\) 的子树大小减去 \(v\) 子树内极大的、颜色也是 \(c\) 的子树大小。
用一个 vector 存储现在颜色是 \(c\) 的极大子树有哪些,和一个 \(cs\) 数组表示颜色为 \(c\) 的子树大小之和。
我们在 dfs 到 \(v\) 前后计算 \(cs_c\) 的增量 \(del\), 其代表的是 \(v\) 子树内颜色为 \(c\) 的极大子树大小的和。
那么这个连通块的大小就是 \(siz_v-del\) 了。
树上差分,\(v\) 的连通块的所有点贡献都加上了 \(n-(siz_v-del)\),
具体是在 \(v\) 加上贡献,在 \(v\) 内的极大子树减去贡献,然后从根节点开始加这个差分。

code
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,m,col[N],dfn[N],num,siz[N],cs[N];
long long d[N];
vector<int> e[N];
vector<int> vec[N];
void dfs(int u,int fa) {
	dfn[u]=++num; siz[u]=1;
	int c=col[u];
	for(int v:e[u]) {
		if(v==fa) continue;
		int cs0=cs[c];
		dfs(v,u);
		int ss=siz[v]-(cs[c]-cs0);
		cs[c]=siz[v]+cs0;
		d[v]+=ss;
		siz[u]+=siz[v];
		for(; vec[c].size(); ) {
			if(dfn[vec[c].back()]>dfn[u]) {
				d[vec[c].back()]-=ss;
				vec[c].pop_back();
			} else break;
		}
	}
	vec[c].push_back(u);
	cs[c]++;
}
void dfs2(int u,int fa) {
	for(int v:e[u]) {
		if(v==fa) continue;
		d[v]+=d[u];
		dfs2(v,u);
	}
}
int main() {
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&col[i]),m=max(m,col[i]);
	for(int i=1,u,v; i<n; i++) {
		scanf("%d%d",&u,&v);
		e[u].push_back(v); e[v].push_back(u);
	}
	dfs(1,1);
	int tot=0;
	for(int c=1; c<=m; c++) {
		if(vec[c].size()) {
			tot++;
			d[1]+=n-cs[c];
			for(; vec[c].size(); ) {
				d[vec[c].back()]-=n-cs[c];
				vec[c].pop_back();
			}
		}
	}
	dfs2(1,1);
	for(int i=1; i<=n; i++) {
		printf("%lld\n",1ll*tot*n-d[i]);
	}
	return 0;
}

标签:hpz,连通,颜色,int,siz,problems,vec,cs,2023.9
From: https://www.cnblogs.com/Simon-Gao/p/17675533.html

相关文章

  • 2023.9
    已经九月了......1.SlidingWindowSort拜谢阿兰赵大神。首先考虑这个过程和UNRD2T1其实还挺像的:当执行\(n-m+1\)次操作后,最大的\(m-1\)个人一定会按大小顺序排在最后。所以我们先来考虑\(k=n-m+1\)的,然后容易发现\(k\ltn-m+1\)也能套用这个方法解决(我们不关注未......
  • 2023.9.2
    昨天晚上忘记写随笔了,主要当时在写新生平台的题,忘写了。把四道pwn题给做完了今天竞赛,下午去了趟416,结果竞赛的pwn题一道不会做,第一题就因为架构原因没法放ida里分析,第二题看题目是堆的题目我还没学,第三题分析了半天分析不出什么漏洞。又看了一会儿没看出什么名堂,就去继续看ctfwik......
  • 2023.9.2-假期周进度报告
    本周,主要进行休息,将社会实践照片进行了一个简单的整理,并且完成返校的基本准备,并成功返校。本周日,主要进行休息,完成了一天简单的休息,遇到了返校要准备什么东西的问题,解决方法是过几天再说吧,等开学前一两天再思考吧,现在时间还早。本周一,主要进行休息,完成了又一天简单的休息,遇到了......
  • 2023.9 练习
    \(9.1\)鸽。\(9.2\)模拟赛。\[100+56+10=166\]难度大概是\([2300,2400]+[2900,3300]+?\)。\(\text{A}\):给定一个正整数序列\(\{a_n\}\),和一个初始全\(0\)的整数序列\(\{b_n\}\),每单位时间\(\foralli\in[1,n],b_i\getsb_i+1\)。定义对于\(b_j\)的一次操作为......
  • 2023.9.1 AT practise
    ARC072F设“热量”为\(T_1V_1+T_2V_2+...\),最后要求的温度就是\(\dfrac{T_1V_1+T_2V_2+...}{V_1+V_2+...}\),由于最后体积是恒定的,那么我们只需要解决热量的问题即可。设\(f_{i,x}\)表示第\(i\)天晚上只能留下\(x\)升水的最大热量。如果我们把写成函数\(f_i(x)\),我们......
  • 《开学记》2023.9.1
    我是傻逼 今早临走之前特意在洛谷上打卡,发现是中吉。  只是这分班结果......RP未免+太过头了,感觉可以去买彩票了。上了语文数学英语化学道法历史,好像除了物理都上了。一个假期没学whk,什么都听不懂。我是智障,开学雷击。上着道法课从门外看到了信息老师的身影,于是一下课追......
  • 每日小记2023.9.1
    内存管理对堆而言的,程序在运行时主动从堆上申请内存,这些内存通过go的内存分配器分配,由垃圾回收器回收。栈是每个goroutine独有的,不需要在操作的时候加锁,而堆上的内存有时需要加锁防止多线程冲突。对程序上的内存回收需要通过标记清除阶段,比如采用三色标记法。对栈而言,他的分配和释......
  • AI辅助编程测试2023.9.1
    今天考虑做一个需求WinForm程序中,将DevExpress中的SpreadsheetControl控件的[Ctrl+S]快捷键禁掉,避免用户自行将程序中提供的表格进行另存。我将下面这句话拿给各个AI工具,以及搜索工具关键词:DevExpress的SpreadsheetControl控件,如何能禁用ctrl+S这个快捷键  POE中的chatGPT3......
  • 胡萝卜问题 Carrot Problems
    Refhttps://www.atvbt.com/the-carrot-problem/......
  • Burp Suite Professional / Community 2023.9 (macOS, Linux, Windows) - Web 应用安
    BurpSuiteProfessional/Community2023.9(macOS,Linux,Windows)-Web应用安全、测试和扫描BurpSuiteProfessional,Test,find,andexploitvulnerabilities.请访问原文链接:https://sysin.org/blog/burp-suite-pro-2023/,查看最新版。原创作品,转载请保留出处。作者......