刷题记录:牛客NC200179Colorful Tree 奇奇怪怪的dfs序

news2024/10/7 14:32:54

传送门:牛客

题目描述:

A tree structure with some colors associated with its vertices and a sequence of commands on it are 
given. A command is either an update operation or a query on the tree. Each of the update operations 
changes the color of a specified vertex, without changing the tree structure. Each of the queries asks 
the number of edges in the minimum connected subgraph of the tree that contains all the vertices of 
the specified color.
Your task is to find answers of each of the queries, assuming that the commands are performed in 
the given order.
输入:
5 
1 2 
2 3 
3 4 
2 5 
1 2 1 2 3 
11 
Q 1 
Q 2 
Q 3 
Q 4 
U 5 1 
Q 1 
U 3 2 
Q 1 
Q 2 
U 5 4 
Q 1
输出:
2 
2 
0 
-1 
3 
2 
2 
0

一道比较难想的树形结构题吧.

对于这道题我们解决的是对于新加入的这个点所增加的贡献是多少,我们可以画个图来帮助理解一下.对于一个改变的一个k,与原来的两个点<u,v>,我们有以下几种关系.

在这里插入图片描述

假设此时的三个点(u,v,g)的颜色是相同的,那么对于此时新增的三个可能位置 k 1 , k 2 , k 3 k1,k2,k3 k1,k2,k3来说,假设新增的是k2,我们会发现新增的贡献就是
( d i s ( k , u ) + d i s ( k , v ) − d i s ( u , v ) ) / 2 (dis(k,u)+dis(k,v)-dis(u,v))/2 (dis(k,u)+dis(k,v)dis(u,v))/2或者 ( d i s ( k , u ) + d i s ( k , g ) − d i s ( u , g ) ) / 2 (dis(k,u)+dis(k,g)-dis(u,g))/2 (dis(k,u)+dis(k,g)dis(u,g))/2
假设此时新增的是k3,我们会发现此时新增的贡献还是:
( d i s ( k , u ) + d i s ( k , v ) − d i s ( u , v ) ) / 2 (dis(k,u)+dis(k,v)-dis(u,v))/2 (dis(k,u)+dis(k,v)dis(u,v))/2
假设此时新增的是k,我们会发现新增的贡献是:
( d i s ( k , u ) + d i s ( k , g ) − d i s ( u , g ) ) / 2 (dis(k,u)+dis(k,g)-dis(u,g))/2 (dis(k,u)+dis(k,g)dis(u,g))/2或者(dis(k,v)+dis(k,g)-dis(v,g))/2
那么此时我们会发现存在这样的一个规律,就是对于新加的一个点k来说,此时我们需要找到之前颜色与之相同的所有点,然后找到一个dfs序里他最近的一个点u,然后再随便的找另一个点v,那么对于此时的新增的贡献来说就是 ( d i s ( k , u ) + d i s ( k , v ) − d i s ( u , v ) ) / 2 (dis(k,u)+dis(k,v)-dis(u,v))/2 (dis(k,u)+dis(k,v)dis(u,v))/2
为了解题方便起见,我们可以规定v的dfs序刚好是离k第二近的一个点.对于找点可以使用二分进行解决

我们先求出所有点的dfs序,然后对于新加的点,我们直接对这个颜色加上相应的贡献.此时需要注意的一点是当我们的颜色只有一个点时,此时我们规定上述的u,v都是这个点.然后对于删除的点,我们删除他此时的贡献即可.假设一个颜色没有点了,此时我们将其的ans改为-1

因为我们需要进行删除与增加操作,以及排序操作,对于维护这些性质我们可以使用 s e t set set进行解决.
对于求解树上两点之间距离,我们可以使用树链剖分或者倍增来求LCA进行求解,此处就不再赘述了.

下面是具体的代码部分:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define maxn 1000000
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
int n;
vector<int>edge[maxn];
int fa[maxn],Size[maxn],max_son[maxn],dep[maxn];
int dfsn[maxn],dfscnt=0,rev[maxn];
void dfs1(int u,int per_u) {
	Size[u]=1;dfsn[u]=++dfscnt;rev[dfscnt]=u;
	for(int i=0;i<edge[u].size();i++) {
		int v=edge[u][i];
		if(v==per_u) continue;
		dep[v]=dep[u]+1;
		dfs1(v,u);
		Size[u]+=Size[v];fa[v]=u;
		if(Size[v]>Size[max_son[u]]) {
			max_son[u]=v;
		}
	}
}
int top[maxn];
void dfs2(int u,int t) {
	top[u]=t;
	if(!max_son[u]) return ;
	dfs2(max_son[u],t);
	for(int i=0;i<edge[u].size();i++) {
		int v=edge[u][i];
		if(v==fa[u]||v==max_son[u]) continue;
		dfs2(v,v);
	}
}
int LCA(int u,int v) {
	while(top[u]!=top[v]) {
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		u=fa[top[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	return u;
}

/*====================================================================*/

set<int>c[maxn];int ans_c[maxn];int a[maxn];
int get_dist(int u,int v) {
	return dep[rev[u]]+dep[rev[v]]-2*dep[LCA(rev[u],rev[v])];
}
void add(int pos,int color) {
	if(c[color].size()==0) {
		c[color].insert(pos);ans_c[color]=0;
		return ;
	}
	auto p=c[color].lower_bound(pos);
	if(p==c[color].begin()||p==c[color].end()) {
		auto x=c[color].begin();auto y=c[color].rbegin();
		ans_c[color]+=(get_dist(pos,*x)+get_dist(pos,*y)-get_dist(*x,*y))/2;
	}
	else {
		auto x=p;auto y=p;x--;
		ans_c[color]+=(get_dist(pos,*x)+get_dist(pos,*y)-get_dist(*x,*y))/2;
	}
	c[color].insert(pos);
}
void del(int pos,int color) {
	if(c[color].size()==1) {
		c[color].erase(pos);ans_c[color]=-1;
		return ;
	}
	c[color].erase(pos);
	auto p=c[color].lower_bound(pos);
	if(p==c[color].begin()||p==c[color].end()) {
		auto x=c[color].begin();auto y=c[color].rbegin();
		ans_c[color]-=(get_dist(pos,*x)+get_dist(pos,*y)-get_dist(*x,*y))/2;
	}
	else {
		auto x=p;auto y=p;x--;
		ans_c[color]-=(get_dist(pos,*x)+get_dist(pos,*y)-get_dist(*x,*y))/2;
	}
}
int main() {
	n=read();
	for(int i=1;i<=n-1;i++) {
		int u=read(),v=read();
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	memset(ans_c,-1,sizeof(ans_c));
	dfs1(1,0);dfs2(1,1);
	for(int i=1;i<=n;i++) {
		a[i]=read();
		add(dfsn[i],a[i]);
	}
	int q=read();
	for(int i=1;i<=q;i++) {
		string opt;cin>>opt;
		if(opt=="Q") {
			int color=read();
			printf("%d\n",ans_c[color]);
		}
		else {
			int pos=read(),color=read();
			del(dfsn[pos],a[pos]);
			add(dfsn[pos],color);a[pos]=color;
		}
	}
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

论文阅读 - End-to-End Wireframe Parsing

文章目录1 概述2 L-CNN2.1 整体架构2.2 backbone2.3 juction proposal module2.4 line sample module2.5 line verificatoin module3 评价指标参考资料1 概述 本文是ICCV2019的一篇论文&#xff0c;核心是提出了一种简单的end-to-end的two-stage的检测图像中线段的方法。同时&…

192、【动态规划】leetcode ——64. 最小路径和:回溯法+动态规划(C++版本)

题目描述 原题链接&#xff1a;64. 最小路径和 解题思路 &#xff08;1&#xff09;回溯法 分别向右或下进行探查 class Solution { public:int res INT_MAX;void backtracking(vector<vector<int>>& grid, int x, int y, int pathSum) {// 超出边界&…

高可用 - 08 Keepalived集群中Master和Backup角色选举策略

文章目录概述实例说明“weight”值为正数“weight”值为负数总结概述 在Keepalived集群中&#xff0c;其实并没有严格意义上的主、备节点&#xff0c;虽然可以在Keepalived配置文件中设置“state”选项为“MASTER”状态&#xff0c;但是这并不意味着此节点一直就是Master角色。…

Python实现人脸识别,进行视频跟踪打码,羞羞的画面统统打上马赛克

哈喽兄弟们&#xff0c;我是轻松~ 今天我们来实现用Python自动对视频打马赛克前言准备工作代码实战效果展示最后前言 事情是这样的&#xff0c;昨天去表弟家&#xff0c;用了下他的电脑&#xff0c;不小心点到了他硬盘里隐藏的秘密&#xff0c;本来我只需要用几分钟电脑的&…

第一章初识Linux

文章目录Linux简介LInux的应用领域Linux OS和各种发行版的关系Linux和Unix的关系Linux相关环境配置图解VM和Linux的关系Linux自定义分三个区VMware网络连接的三种模式桥接模式NAT模式主机模式VMware快照功能Linux的操作方式Linux的目录结构各种Linux发行版本的常见目录注意事项…

GO进阶(5) 垃圾回收机制

一、前言 1、垃圾回收背景 编程语言通常会使用手动和自动两种方式管理内存&#xff0c;C、C 以及 Rust 等编程语言使用手动的方式管理内存&#xff0c;工程师需要主动申请或者释放内存&#xff1b;而 Python、Ruby、Java 和 Go 等语言使用自动的内存管理系统&#xff0c;一般都…

Java八股——wait、sleep与park

sleep()、wait()、park()都可以使线程进入等待状态&#xff0c;但是3种方式在使用上和功能上都有些不同。 共同点: wait()&#xff0c;wait(long)和sleep(long)的效果都是让当前线程暂时放弃CPU的使用权&#xff0c;进入阻塞状态它们都可以被打断唤醒都是native方法执行sleep…

java四种线程池(基本使用)

标题java四种线程池及使用示例 1、线程工厂 1、我们先来写ThreadFactory&#xff0c;在创建线程池时候可以传入自定义的线程工厂&#xff0c;线程工厂说白了就是用来定制线程的一些属性&#xff1a;名字、优先级、是否为守护线程。直接看代码即可。 当然创建线程池的时候可以…

控制台运行java

控制台执行java 新建java代码 新建一个记事本文件&#xff0c;将文件名改为HelloWorld.java&#xff0c;注意&#xff1a;后缀是.java。 若没有显示文件后缀&#xff0c;可以在资源管理器打开显示后缀&#xff0c;然后再次修改文件名&#xff0c;一定要修改成文件类型是java…

缺陷及缺陷管理

今日目标能够说出缺陷的判定标准能够说出描述缺陷的6大核心内容能够描述缺陷状态、严重程度、优先级的作用能够按照提供的缺陷模版完成一个缺陷的提交能够说出缺陷的跟踪流程能够在禅道中提交测试用例能够在禅道中提交缺陷1. 缺陷1.1 缺陷的定义&#xff08;重点&#xff09;产…

Python3.8.8-Django3.2-Redis-连接池-数据类型-字符串-list-hashmap-命令行操作

文章目录1.认识Redis1.1.优点1.2.缺点2.在Django中Redis的连接3.Redis的基础用法3.1.hashmap结构3.2.list结构4.命令行查看数据库5.作者答疑1.认识Redis Remote DIctionary Server(Redis) 是一个key-value 存储系统&#xff0c;是跨平台的非关系型数据库。是一个开源的使用 AN…

Linux入门篇-Linux目录结构

简介 简单介绍Linux目录。 Linux的⽬录结构 “/”表示根⽬录&#xff0c;根⽬录是Linux⽬录结构中的最顶级的⽬录&#xff0c;类似于windows的C:\ D:\ /boot⽬录&#xff1a;存放的是系统的启动配置⽂件和内核⽂件 /dev⽬录&#xff1a;存放的是Linux的设备⽂件 /etc⽬录&…

Nacos新手详细知识大全

官网&#xff1a;Spring Cloud Alibaba一、Nacos快速入门1.1 服务注册到Nacos1.1.1 配置**引入com.alibaba.cloud&#xff0c;**以后的版本就不用操心了<!-- com.alibaba.cloud--><!-- com.alibaba.cloud--><dependency><groupId>com.alibaba.cloud<…

SpringCloud之 LoadBalancer负载均衡

文章目录LoadBalancer 负载均衡一、LoadBalanced 负载均衡二、自定义负载均衡三、OpenFeign 实现负载均衡①添加依赖②启动类添加 EnableFeignClients③创建客户端接口 UserClient④service业务中调用客户端接口提示&#xff1a;以下是本篇文章正文内容&#xff0c;SpringCloud…

pv和pvc

一、PV和PVC详解当前&#xff0c;存储的方式和种类有很多&#xff0c;并且各种存储的参数也需要非常专业的技术人员才能够了解。在Kubernetes集群中&#xff0c;放了方便我们的使用和管理&#xff0c;Kubernetes提出了PV和PVC的概念&#xff0c;这样Kubernetes集群的管理人员就…

【Python】torch.einsum()解析

【Python】torch.einsum()解析 文章目录【Python】torch.einsum()解析1. 介绍2. 示例2.1 Pytorch矩阵乘法2.2 Numpy高阶张量3. 参考1. 介绍 爱因斯坦简记法&#xff1a;是一种由爱因斯坦提出的&#xff0c;对向量、矩阵、张量的求和运算 ∑\sum∑ 的求和简记法。在该简记法当中…

链表面试题

链表面试题1. 删除链表中等于给定值 val 的所有结点。2. 反转一个单链表。3. 给定一个带有头结点 head 的非空单链表&#xff0c;返回链表的中间结点。如果有两个中间结点&#xff0c;则返回第二个中间结点。4. 输入一个链表&#xff0c;输出该链表中倒数第k个结点。5. 将两个有…

延时任务的四种实现方式

什么是延迟任务&#xff1f;顾明思议&#xff0c;我们把需要延迟执行的任务叫做延迟任务。延迟任务的使用场景有以下这些&#xff1a;红包 24 小时未被查收&#xff0c;需要延迟执退还业务&#xff1b;每个月账单日&#xff0c;需要给用户发送当月的对账单&#xff1b;订单下单…

计算机网络之MAC和IP地址

MAC地址 在局域网中&#xff0c;硬件地址&#xff0c;又称为物理地址或MAC地址。 目前现在的局域网中实际上使用的都是6字节的MAC地址&#xff0c;所以每一个以太网设备都具有唯一的MAC地址。 MAC地址的格式 假设传输使用的是IP数据&#xff0c;V2的MAC帧较为简单&#xff…

Sonar:VSCode配置SonarLint/SonarLint连接SonarQube

需求描述 公司为项目代码配置了Sonar检测&#xff0c;希望在VSCode中开发项目时能够同步检测结果。 注意事项 SonarQube版本必须为7.9&#xff0c;否则SonarLint无法连接&#xff08;GitHub-SonarLint-Wiki第一行就有说明&#xff09;&#xff01;&#xff01;&#xff01;S…