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: 小明希望你 ...
随机推荐
- PHP-FPM 慢执行日志、网站隔离配置
慢执行日志 1.配置文件下打开慢执行日志 vim /usr/local/php/etc/php-fpm.conf # 慢执行日志路径 slowlog = /path/to/slow.log # 设置超 ...
- error C2665: “std::locale::facet::operator new”: 2 个重载中没有一个可以转换所有参数类型
qt项目 qt creator项目由插件自动转换成的vs2015项目,为了发布少带些dll ,切换成vs2013项目,在更改了一些vs2013不支持的c++新标准写法之后,release可正常编过,但 ...
- NOIP 统计单词个数
描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的单词个 ...
- [翻译]用PostCSS改善你的CSS代码质量
“代码质量”这个术语对于程序员来说并不陌生.毕竟,每个开发人员都知道,代码只是能工作是不够的.它还应该具备其他要素:它应该是可读的,良好的格式和一致性.它也应该符合一些标准的量化指标.不过这些在写CS ...
- 数据结构(二) 树Tree
五.树 树的定义 树的逻辑表示:树形表示法.文氏图表示法.凹入表示法.括号表示法. 结点:表示树中的元素,包括数据项及若干指向其子树的分支. 结点的度:结点拥有的子树树:树的度:一 ...
- C语言细节注意
前段时间用C语言写了个小的程序,也算是复习了下好久没有用的C语言.也是有好多的坑了,哈哈. 1.C语言的结构体 结构体的命名最好能够做到规范.因为不同的 编译环境下,不是很规范的命名有时候会导致莫名其 ...
- ubuntu 14.04 建立wifi热点
昨天突然想起来我可以用笔记本搞一个热点这样我的手机就不用上流量了,但是手机死活搜不到建好的信号,目前的解决方案如下: 直接用ubuntu自带的创建wifi网络功能是不好使的,因为android系统不支 ...
- Word Search, 在矩阵中寻找字符串,回溯算法
问题描述: Given a 2D board and a word, find if the word exists in the grid. The word can be constructed ...
- JDK_如何查看安装的jdk是32位还是64位?
1. 1.1.32位系统只能装 32位 jdk 1.2.64位系统,安装的 32位JDK 和 64位JDK 是不同的目录 1.2.1.32位的路径 类似:C:\Program Files (x86)\ ...
- 浅谈 session 会话的原理
先谈 cookie 网络传输基于的Http协议,是无状态的协议,即每次连接断开后再去连接,服务器是无法判断此次连接的客户端是谁. 如果每次数据传输都需要进行连接和断开,那造成的开销是很巨大的. 为了解 ...