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 ...
随机推荐
- 第三章:使用 Android Studio 编程[Learn Android Studio 汉化教程]
Learn Android Studio 汉化教程 Android Studio 本章包含如何在Android Studio中书写或生成代码. Android Studio 使用面向对象编程的思想来生 ...
- svn删除
[本地删除.然后提交到服务器]与[服务器删除然后本地更新] svn delete svn://路径(目录或文件的全路径) -m “删除备注信息文本” 推荐如下操作: svn delete 文件名 sv ...
- Python,OpenGL生命游戏
初学Python和OpenGL,练手的第一个小程序life.py,这个小程序在日后会不断调整,增加类.优化判断及操作 执行效果: 按正规生命游戏的规则: 1.周围生命等于3时产生生命 2.周围生命等于 ...
- sql之分段统计
sql之分段统计 需求:获取一个县所有家庭人数在1-2人,3-4人,5-6人,6人以上的家庭数的数组 思路:通过CASE WHEN 将 CBFCYSL分组,然后统计数据条数. 语句: SELECT T ...
- leetcode526
public class Solution { //回溯法 //根据回溯的思路,同样,可以对本题的Beautiful排列实现. //比如,当N为5时,使用回溯算法先是得到(1,2,3,4,5)排列,符 ...
- Spring boot + Gradle + Eclipse打war包发布总结
首先感谢两位博主的分享 http://lib.csdn.net/article/git/55444?knId=767 https://my.oschina.net/alexnine/blog/5406 ...
- Spring 学习记录4 ResourceLoader
ResourceLoader Spring的ApplicationContext继承了ResourceLoader接口.这个接口主要就是可以加载各种resource.. 接口还是比较简单的: /* * ...
- webService 入门级
1,建立一个项目名为Trans,web项目,普通java项目都可以!这里我们就以简单的java应用程序来作为示范吧! 1.1在建立一个方法属于com.shu.function.Function类: / ...
- Python常见函数用法
1. shape()函数 在numpy模块 输入参数:类似数组(比如列表,元组)等,或是数组 返回:一个整型数字的元组,元组中的每个元素表示相应的数组每一维的长度 # shape[0]返回对象的行数, ...
- IOS学习经验总结
学习ios有一段时间了,感觉有些盲目.有些迷茫,从网上收集了一些比人的学习经验,来参考. IOS学习经验总结--来自知乎网友 转自知乎:http://www.zhihu.com/question/20 ...