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(十棵线段树的树链剖分)的更多相关文章

  1. 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree

    原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...

  2. 1369 - Answering Queries(规律)

    1369 - Answering Queries   PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 32 M ...

  3. gym 100589A queries on the Tree 树状数组 + 分块

    题目传送门 题目大意: 给定一颗根节点为1的树,有两种操作,第一种操作是将与根节点距离为L的节点权值全部加上val,第二个操作是查询以x为根节点的子树的权重. 思路: 思考后发现,以dfs序建立树状数 ...

  4. 1369 - Answering Queries

    1369 - Answering Queries    PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 32 ...

  5. 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 ...

  6. 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 < ...

  7. GSS7 spoj 6779. Can you answer these queries VII 树链剖分+线段树

    GSS7Can you answer these queries VII 给出一棵树,树的节点有权值,有两种操作: 1.询问节点x,y的路径上最大子段和,可以为空 2.把节点x,y的路径上所有节点的权 ...

  8. 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 ...

  9. 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 ...

随机推荐

  1. 从windows拷贝到linux的脚本报错:未找到命令 or 语法错误

    可能真的是命令拼错了或者参数有误,也可能是语法错误. 但是但是但是,如果之前脚本运行的好好的,没做任何改动或者仅仅改了一丁点儿. 那么脚本可能在格式上存在问题,解决方案: 安装dos2unix sud ...

  2. apt-get upgarde 和dist-upgrade的差别

    Debian/Ubuntu Linux都使用apt,升级时都是: apt-get update apt-get upgrade apt-get dist-upgrade 安装或升级系统分下面几个步骤. ...

  3. 经典CNN模型计算量与内存需求分析

    表1 CNN经典模型的内存,计算量和参数数量对比 AlexNet VGG16 Inception-v3 模型内存(MB) >200 >500 90-100 参数(百万) 60 138 23 ...

  4. leetcode686

    /* 上来的想法是KMP的思想,但是具体不会KMP的实现,c++STL的string 中的find?但是要注意A的长度与B的长度的问题,首先A的长度要大于B的长度 分为三个阶段: 1. A比B的长度要 ...

  5. Dreamweaver 中文乱码

     定义当前页面的编码属性      Ctrl+j 标题/编码 将编码改成UTF8即可     PhpStorm    FILE->Setting->File Encoding->将U ...

  6. Java ArrayList的不同排序方法

    本文由 ImportNew - 温布利往事 翻译自 dzone.欢迎加入翻译小组.转载请见文末要求. 由于其功能性和灵活性,ArrayList是 Java 集合框架中使用最为普遍的集合类之一.Arra ...

  7. 【309】◀▶ Windows 相关功能实现

    目录: 共享文件夹失败的解决方法 导 栅 添 1. 共享文件夹失败的解决方法 参考:解决“你没有权限访问,请与网络管理员联系” 参考:WIN7局域网文件共享设置方法 2. 导 在 3. 栅 栅 4. ...

  8. ubuntu 安装 rtpengine

    摘要 RtpEngine推荐使用Debian系统,可以看出Debian系统的安装是最简单的.我是基于ubuntu18.04安装的.需要注意的是如果你的Ubuntu系统版本太低,安装时会遇到各种的版本太 ...

  9. java 内存溢出

    不健壮代码的特征及解决办法 1.尽早释放无用对象的引用.好的办法是使用临时变量的时候,让引用变量在退出活动域后,自动设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露. 对于仍然有指针指向的 ...

  10. 如何用shell脚本执行或关闭jar包服务?

    现在springboot很流行,但是大家都知道springboot是以jar包的方式进行打包的,那样就少不了开启或关闭服务的操作了,但是命令方式未免过于繁琐. 下面记录shell脚本的方式启动或关闭服 ...