UVA - 12424 Answering Queries on a Tree(十棵线段树的树链剖分)
You are given a tree with N nodes. The tree nodes are numbered from 1 to N and have colors C1, C2,
. . . , CN initially. You have to handle M instructions on the tree of the following forms:
• 0 u c: Change the color of node u to c.
• 1 u v: Output the maximum number of times a color appeared on the unique path from node u
to node v.
Input
The first line of input contains T (1 ≤ T ≤ 10) which is the number of test cases. The first line of each
test case contains two integers N and M (1 ≤ N, M ≤ 105
). Next line contains N space separated
integers C1, C2, . . . , CN (1 ≤ Ci ≤ 10) denoting the initial colors of the nodes. Each of the next N − 1
lines contain two integers a and b (1 ≤ a, b ≤ N and a ̸= b) meaning that there is an edge between
node a and node b. Each of the next M lines contains an instruction of one of the two forms described
above. For all the instructions: 1 ≤ u, v ≤ N and 1 ≤ c ≤ 10.
Output
For each of the second type instruction output the answer in one line.
Sample Input
2
5 6
3 2 1 2 3
1 2
2 3
2 4
1 5
1 3 5
0 1 1
0 2 1
1 3 5
0 2 4
1 2 4
2 1
5 6
1 2
1 2 2
Sample Output
2
3
1
1
题意:给你一颗树,树上的每个节点都有颜色,颜色编号在1-10之间,给出两种操作
操作一:将树上x点的颜色搞成val
操作二:求点u到点v路径上最多的颜色有几个
题解:颜色很少,所以不用树上莫队,可以建10棵线段树,如果一个点的颜色为ai,则在ai编号的线段树上该点为1,其他编号的树上该点为0
然后每次跑路径的时候跑十遍,记下路径和最大的一种颜色输出,就是答案了,emmm,真暴力啊QAQ
因为涉及到树上路径,所以树链剖分即可了
代码如下:
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lson root<<1
#define rson root<<1|1
using namespace std; struct seg_tree
{
struct node
{
int l,r,sum;
} tr[]; void push_up(int root)
{
tr[root].sum=tr[lson].sum+tr[rson].sum;
} void build(int root,int l,int r)
{
if(l==r)
{
tr[root].l=l;
tr[root].r=r;
return ;
}
tr[root].l=l;
tr[root].r=r;
int mid=(l+r)>>;
build(lson,l,mid);
build(rson,mid+,r);
} void update(int root,int pos,int val)
{
if(tr[root].l==pos&&tr[root].r==pos)
{
tr[root].sum=val;
return ;
}
int mid=(tr[root].l+tr[root].r)>>;
if(pos<=mid)
{
update(lson,pos,val);
}
else
{
update(rson,pos,val);
}
push_up(root);
} int query(int root,int l,int r)
{
if(tr[root].l==l&&tr[root].r==r)
{
return tr[root].sum;
}
int mid=(tr[root].l+tr[root].r)>>;
if(mid<l)
{
return query(rson,l,r);
}
else
{
if(mid>=r)
{
return query(lson,l,r);
}
else
{
return query(lson,l,mid)+query(rson,mid+,r);
}
}
} void dfs(int root,int l,int r)
{
if(l==r)
{
return ;
} int mid=(l+r)>>;
dfs(lson,l,mid);
dfs(rson,mid+,r);
}
} tree[]; vector<int> g[];
int fa[],deep[],size[],son[],id[],c[],w[],top[],cnt; void dfs1(int now,int f,int dep)
{
fa[now]=f;
deep[now]=dep;
size[now]=;
int maxson=-;
for(int i=; i<g[now].size(); i++)
{
if(g[now][i]==f)
{
continue;
}
dfs1(g[now][i],now,dep+);
size[now]+=size[g[now][i]];
if(size[g[now][i]]>maxson)
{
maxson=size[g[now][i]];
son[now]=g[now][i];
}
}
} void dfs2(int now,int topf)
{
id[now]=++cnt;
w[cnt]=c[now];
top[now]=topf;
if(!son[now])
{
return ;
}
dfs2(son[now],topf);
for(int i=; i<g[now].size(); i++)
{
if(fa[now]==g[now][i]||g[now][i]==son[now])
{
continue;
}
dfs2(g[now][i],g[now][i]);
}
} void point_update(int u,int val)
{
for(int i=; i<=; i++)
{
if(val==i)
{
tree[i].update(,id[u],);
}
else
{
tree[i].update(,id[u],);
}
}
} int path_query(int u,int v,int val)
{
int ans=;
while(top[u]!=top[v])
{
if(deep[top[u]]<deep[top[v]])
{
swap(u,v);
}
ans+=tree[val].query(,id[top[u]],id[u]);
u=fa[top[u]];
}
if(deep[u]>deep[v])
{
swap(u,v);
}
ans+=tree[val].query(,id[u],id[v]);
return ans;
} int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
memset(tree,,sizeof(tree));
memset(fa,,sizeof(fa));
memset(son,,sizeof(son));
memset(deep,,sizeof(deep));
memset(size,,sizeof(size));
memset(id,,sizeof(id));
memset(c,,sizeof(c));
memset(w,,sizeof(w));
memset(top,,sizeof(top));
cnt=;
for(int i=;i<=;i++)
{
g[i].clear();
}
scanf("%d%d",&n,&m);
for(int i=; i<=n; i++)
{
scanf("%d",&c[i]);
}
for(int i=; i<n; i++)
{
int from,to;
scanf("%d%d",&from,&to);
g[from].push_back(to);
g[to].push_back(from);
}
dfs1(,,);
dfs2(,);
for(int i=; i<=; i++)
{
tree[i].build(,,n);
}
for(int i=; i<=n; i++)
{
tree[w[i]].update(,i,);
}
for(int i=; i<=m; i++)
{
int kd,l,r;
scanf("%d%d%d",&kd,&l,&r);
if(kd==)
{
int ans=;
for(int j=; j<=; j++)
{
ans=max(ans,path_query(l,r,j));
}
printf("%d\n",ans);
}
else
{
if(kd==)
{
point_update(l,r);
} }
}
} }
UVA - 12424 Answering Queries on a Tree(十棵线段树的树链剖分)的更多相关文章
- 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree
原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...
- 1369 - Answering Queries(规律)
1369 - Answering Queries PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 32 M ...
- gym 100589A queries on the Tree 树状数组 + 分块
题目传送门 题目大意: 给定一颗根节点为1的树,有两种操作,第一种操作是将与根节点距离为L的节点权值全部加上val,第二个操作是查询以x为根节点的子树的权重. 思路: 思考后发现,以dfs序建立树状数 ...
- 1369 - Answering Queries
1369 - Answering Queries PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 32 ...
- Codeforces Round #329 (Div. 2) D. Happy Tree Party LCA/树链剖分
D. Happy Tree Party Bogdan has a birthday today and mom gave him a tree consisting of n vertecie ...
- HDU 4718 The LCIS on the Tree(树链剖分)
Problem Description For a sequence S1, S2, ... , SN, and a pair of integers (i, j), if 1 <= i < ...
- GSS7 spoj 6779. Can you answer these queries VII 树链剖分+线段树
GSS7Can you answer these queries VII 给出一棵树,树的节点有权值,有两种操作: 1.询问节点x,y的路径上最大子段和,可以为空 2.把节点x,y的路径上所有节点的权 ...
- Codeforces Round #329 (Div. 2) D. Happy Tree Party 树链剖分
D. Happy Tree Party Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/593/p ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
随机推荐
- 深入浅出 Java Concurrency (13): 锁机制 part 8 读写锁 (ReentrantReadWriteLock) (1)
从这一节开始介绍锁里面的最后一个工具:读写锁(ReadWriteLock). ReentrantLock 实现了标准的互斥操作,也就是一次只能有一个线程持有锁,也即所谓独占锁的概念.前面的章节中一 ...
- Zookeeper的几个应用场景
场景一 有这样一个场景:系统中有大约100w的用户,每个用户平 均有3个邮箱账号,每隔5分钟,每个邮箱账需要收取100封邮件,最多3亿份邮件需要下载到服务器中(不含附件和正文).用20台机器划分计算的 ...
- file_get_content服务器对服务器二进制文件上传
1.file_get_contents函数可安全用于二进制对象,适用服务器对服务器文件是上传场景 base64_encode(file_get_contents('1268879774AaCl4wIE ...
- ARM汇编中值滤波实验
其实就是 汇编的排序然后选出中位数 排序写的是最直接的冒泡排序,因为简单. 相应的C代码 r2=r0; while(r1<r0){ r1++; r2=r2-; r3=; while(r3< ...
- leetcode278
/* The isBadVersion API is defined in the parent class VersionControl. bool IsBadVersion(int version ...
- Mysql之数据库设计
一.三大范式 1.第一范式:消除一个字段包含多个数据库值,消除一个记录包含重复的组(单独的一列包含多个项目),即可满足1NF. 2.第二范式:消除部分依赖性即可转化为2NF.部分依赖性表示一个记录中包 ...
- OpenSUSE 安装JAVA环境变量JDK
一.首先卸载虚拟机自带的JDK环境 具体命令: rpm -qa |grep java --查找java信息 rpm –qa|grep jdk --查找jdk信息 如果有依赖关系,提示无法卸载,使 ...
- Stars URAL - 1028
就是给你一些星星的坐标,然后求出每个星星的左下角有多少颗星星 题目保证按照Y坐标的顺序给出每个星星的坐标,那么我们就可以说,当输入某个星星的坐标时,此时有多少个星星的横坐标小于它,它左下角就有多少星星 ...
- 详细探究Spark的shuffle实现
Background 在MapReduce框架中,shuffle是连接Map和Reduce之间的桥梁,Map的输出要用到Reduce中必须经过shuffle这个环 节,shuffle的性能高低直接影响 ...
- Appium+python自动化-Remote远程控制
前言 在第三篇启动app的时候有这样一行代码driver = webdriver.Remote('http://192.168.1.1:4723/wd/hub', desired_caps),很多小伙 ...