HiHoCoder1156 彩色的树(树值的记忆化ORZ+map强势出场)
1156 : 彩色的树
描述
给定一棵n个节点的树,节点编号为1, 2, …, n。树中有n - 1条边,任意两个节点间恰好有一条路径。这是一棵彩色的树,每个节点恰好可以染一种颜色。初始时,所有节点的颜色都为0。现在需要实现两种操作:
1. 改变节点x的颜色为y;
2. 询问整棵树被划分成了多少棵颜色相同的子树。即每棵子树内的节点颜色都相同,而相邻子树的颜色不同。
输入
第一行一个整数T,表示数据组数,以下是T组数据。
每组数据第一行是n,表示树的节点个数。接下来n - 1行每行两个数i和j,表示节点i和j间有一条边。接下来是一个数q,表示操作数。之后q行,每行表示以下两种操作之一:
1. 若为"1",则询问划分的子树个数。
2. 若为"2 x y",则将节点x的颜色改为y。
输出
每组数据的第一行为"Case #X:",X为测试数据编号,从1开始。
接下来的每一行,对于每一个询问,输出一个整数,为划分成的子树个数。
数据范围
1 ≤ T ≤ 20
0 ≤ y ≤ 100000
小数据
1 ≤ n, q ≤ 5000
大数据
1 ≤ n, q ≤ 100000
- 样例输入
-
2
3
1 2
2 3
3
1
2 2 1
1
5
1 2
2 3
2 4
2 5
4
1
2 2 1
2 3 2
1 - 样例输出
-
Case #1:
1
3
Case #2:
1
5
由于无环,和断点(改变颜色的点)连接的点如果颜色和改变前一样,树++。和改变后一样树--。
代码一号,树上乱搞:
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=;
int Laxt[maxn],Next[maxn],To[maxn],cnt;
int ans,V[maxn];void add(int u,int v)
{
Next[++cnt]=Laxt[u];
Laxt[u]=cnt;
To[cnt]=v;
}
void init()
{
ans=;cnt=;
memset(Laxt,,sizeof(Laxt));
memset(V,,sizeof(V));
}
void change(int x,int y)
{
bool flag=false;
int tmp=;
for(int i=Laxt[x];i;i=Next[i]){
if(V[To[i]]==y) ans--;
if(V[To[i]]==V[x]) ans++;
}
V[x]=y;
}
int main()
{
int T,n,i,j,x,y,q,u,v,Case=;
scanf("%d",&T);
while(T--){
printf("Case #%d:\n",++Case);
init();
scanf("%d",&n);
for(i=;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
scanf("%d",&q);
while(q--){
scanf("%d",&x);
if(x==) printf("%d\n",ans);
else {
scanf("%d%d",&x,&y);
change(x,y);
}
}
}
return ;
}
每次访问邻边导致耗时过多。怎么记录?
首先,无向图变有向图,==其实就是父子关系辣。
一个节点记录相邻儿子的信息。如果改变某点,就只改变它父亲的信息就ok。
强势之处:
通过父子关系使记录和查询变成O(1),访问效率高;
map记录每个节点的有效颜色,空间利用效率高。
代码二号:
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
const int maxn=;
int Laxt[maxn],Next[maxn<<],To[maxn<<],cnt;
int ans,V[maxn],fa[maxn];
map<int,int>G[maxn];
void add(int u,int v)
{
Next[++cnt]=Laxt[u];
Laxt[u]=cnt;
To[cnt]=v;
}
void init()
{
ans=;cnt=;
memset(Laxt,,sizeof(Laxt));
memset(V,,sizeof(V));
}
void change(int x,int y)
{
if(V[x]==y) return ;
ans+=G[x][V[x]];
ans-=G[x][y];
if(fa[x]!=){
if(V[fa[x]]==V[x]) ans++;
if(V[fa[x]]==y) ans--;
G[fa[x]][V[x]]--;
G[fa[x]][y]++;
}
V[x]=y;
}
void dfs(int u,int pre)
{
fa[u]=pre;
for(int i=Laxt[u];i;i=Next[i]){
if(To[i]==pre) continue;
G[u][]++;
dfs(To[i],u);
}
}
int main()
{
int T,n,i,x,y,q,Case=;
scanf("%d",&T);
while(T--){
printf("Case #%d:\n",++Case);
init();
scanf("%d",&n);
for(i=;i<=n;i++) G[i].clear();
for(i=;i<n;i++){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs(,);
scanf("%d",&q);
while(q--){
scanf("%d",&x);
if(x==) printf("%d\n",ans);
else {
scanf("%d%d",&x,&y);
change(x,y);
}
}
}
return ;
}
HiHoCoder1156 彩色的树(树值的记忆化ORZ+map强势出场)的更多相关文章
- ZOJ 3644 Kitty's Game dfs,记忆化搜索,map映射 难度:2
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4834 从点1出发,假设现在在i,点数为sta,则下一步的点数必然不能是sta的 ...
- P1040 加分二叉树(树上记忆化搜素)
这道题很水 但我没做出来……………………………… 我写的时候状态设计错了,设计dp[l][m][r]为从l到r以m为根的值 这样写遍历状态就是n^3的,会TLE. 而且写路径的时候是用结构体写的,这样 ...
- 【bzoj5123】[Lydsy12月赛]线段树的匹配 树形dp+记忆化搜索
题目描述 求一棵 $[1,n]$ 的线段树的最大匹配数目与方案数. $n\le 10^{18}$ 题解 树形dp+记忆化搜索 设 $f[l][r]$ 表示根节点为 $[l,r]$ 的线段树,匹配选择根 ...
- 洛谷 2921 记忆化搜索 tarjan 基环外向树
洛谷 2921 记忆化搜索 tarjan 传送门 (https://www.luogu.org/problem/show?pid=2921) 做这题的经历有点玄学,,起因是某个random题的同学突然 ...
- [HNOI2004]L语言 字典树 记忆化搜索
[HNOI2004]L语言 字典树 记忆化搜索 给出\(n\)个字符串作为字典,询问\(m\)个字符串,求每个字符串最远能匹配(字典中的字符串)到的位置 容易想到使用字典树维护字典,然后又发现不能每步 ...
- 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay
正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...
- 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分
树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...
- CF487E Tourists 【圆方树 + 树剖 + 堆】
题目链接 CF487E 题解 圆方树 + 树剖 裸题 建好圆方树维护路径上最小值即可 方点的值为其儿子的最小值,这个用堆维护 为什么只维护儿子?因为这样修改点的时候就只需要修改其父亲的堆 这样充分利用 ...
- 【BZOJ3589】动态树 树链剖分+线段树
Description 别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求你在这棵树上维护两种事件 事件0: 这棵树长出了一些果子, 即某个子树中的每个节点都会长出K个果子. 事件1: 小明希望你 ...
随机推荐
- MapReduce概述
MapReduce 源自于Google的MapReduce论文,Hadoop MapReduce是Google MapReduce克隆版 MapReduce适合PB级以上海量数据的离线处理 MapRe ...
- linux centos7 安装zookeeper
linux 系统下 zookeeper 安装教程 1.下载安装包 1)进入安装目录 cd /home/install/ 2)下载 wget http://mirror.bit.edu.cn/apach ...
- 配置zabbix_server通过zabbix_proxy进行监控Host
zabbix_server添加proxy并监控主机 zabbix分布式监控系统安装配置:http://www.cnblogs.com/LuckWJL/p/9037007.html 安装配置zabbix ...
- 关于在asp.net添加jQuery的智能提示
如果是vs2008以后的版本,一般都会支持jQuery自动提示代码功能,不支持也没关系,很简单的操作就能支持: 1.先为vs下载一个补丁,地址为:http://code.msdn.microsoft. ...
- GRE/GMAT/LSAT长难句300例精讲精练-思维导图
<GRE/GMAT/LSAT长难句300例精讲精练>是GRE超人气名师陈琦老师团队的又一本新作,也是“再要你命3000”的新成员,从之前的词汇.短语.练习,提升到长难句层面,相信学完本书后 ...
- SpringBoot 通用返回类设计
在项目中通常需要为前端设计通过的返回类,返回的格式为: { "status": "success", "data": {...} } 定义通 ...
- select 下拉框 设置值
function setSelectOption(objSelect, targetValue){ if(objSelect){ var options = objSelect.options; if ...
- HUE中oozie执行shell
Oozie执行Shell,传入参数1. 新建一个workflow 2. 拖入一个shell 3. shell脚本如下 #!/bin/sh sqoop import --connect jdbc:mys ...
- mysql官网下载链接——绿色版&安装版
windows64位5.5.60安装版 https://downloads.mysql.com/archives/get/file/mysql-5.5.60-winx64.msi windows64位 ...
- java实现定时任务的三种方法 - 转载
java实现定时任务的三种方法 /** * 普通thread * 这是最常见的,创建一个thread,然后让它在while循环里一直运行着, * 通过sleep方法来达到定时任务的效果.这样可以快速简 ...