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: 小明希望你 ...
随机推荐
- 登录用户执行sudo时报错
场景: 以普通用户登录,登陆后切换至root或其他用户时报错(sudo su -或sudo -i) 报错信息: -bash: /bin/logger: Argument list too long 根 ...
- 20145219 《Java程序设计》实验五 Java网络编程及安全实验报告
20145219 <Java程序设计>实验五 Java网络编程及安全实验报告 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验步骤 我和2 ...
- JavaWeb HTML
1. HTML介绍 1.1. 什么是HTML HTML的全称为Hyper Text Markup Language,译为超文本标记语言. 超文本,就是指页面内可以包含图片.链接,甚至音乐.程序等非文字 ...
- jz2440存储管理实验【学习笔记】
平台:jz2440 作者:庄泽彬(欢迎转载,请注明作者) 说明:韦东山一期视频学习笔记 简介:先来简单的说明一下这次的实验,看看下图,我们的程序通过烧录器下载到nandflash当中去,之后在启动的时 ...
- 关于Block汇总
//使用总结: //1.当block里面会有b类相关的参数要回调回去的时候,属性用copy修饰,将其拷贝到堆里面,这样即便栈释放掉了,b类的指针也在堆中存在,能够成功的回调回去. //Block默认存 ...
- Spring中Value注解的使用
Spring中Value注解的使用 分类: Spring2014-08-16 17:28 2985人阅读 评论(0) 收藏 举报 有的时候我们定义了Properties文件,并且使用Spring的Pr ...
- springBean集合注入的方法
applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xm ...
- 【转】XGBoost 与 Boosted Tree
XGBoost 与 Boosted Tree http://www.52cs.org/?p=429 作者:陈天奇,毕业于上海交通大学ACM班,现就读于华盛顿大学,从事大规模机器学习研究. 注解:tru ...
- selenium学习笔记(鼠标事件)
昨天是简单的操作.之后是复杂的操作 首先是鼠标事件 AcationChains类 鼠标操作的常用方法: 右击 context_click() 双击 double_click() 拖动 dr ...
- redis key 通配符 查询相应的key
keys pattern 查询相应的key 在redis里,允许模糊查询key 有3个通配符 *, ? ,[] *: 通配任意多个字符 ?: 通配单个字符 []: 通配括号内的某1个字符 redis ...