HYSBZ 1036树链剖分
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
Sample Output
4
1
2
2
10
6
5
6
5
16
Hint
树链剖分+线段树模板题:
参考代码:
//树链剖分+线段树
/*
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 (包括u和v本身)
*/
#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof a)
#define mp make_pair
#define eps 1e-8
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
typedef long long ll;
typedef unsigned long long ull;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3fll;
const int maxn=2e5+;
int siz[maxn],top[maxn],fa[maxn],dep[maxn];
int tid[maxn],rnk[maxn],son[maxn],cnt;
int head[maxn],tot,a[maxn]; struct Node{
int v,nxt;
} edge[maxn]; struct Tree{
int l,r,sz;
int sum,max_num;
} tree[maxn<<]; void Init()
{
tot=cnt=;
mem(head,-); mem(son,-);
mem(siz,); mem(top,);
} void Pushup(int pos)
{
tree[pos].max_num=max(tree[pos<<].max_num,tree[pos<<|].max_num);
tree[pos].sum=tree[pos<<].sum+tree[pos<<|].sum;
} void Build(int l,int r,int rt)
{
tree[rt].l=l;tree[rt].r=r;tree[rt].sz=r-l+;
if(l==r)
{
tree[rt].max_num=tree[rt].sum=a[rnk[l]];
return ;
}
int mid=(l+r)>>;
Build(lson); Build(rson);
Pushup(rt);
} void Update(int pos,int c,int l,int r,int rt)
{
if(l==r)
{
tree[rt].max_num=tree[rt].sum=c;
return ;
}
int mid=(l+r)>>;
if(pos<=mid) Update(pos,c,lson);
else Update(pos,c,rson);
Pushup(rt);
} int Query_sum(int L,int R,int l,int r,int rt)//求L~R的和
{
if(l>=L && r<=R) return tree[rt].sum;
int mid=(l+r)>>;
int ans=;
if(L<=mid) ans+=Query_sum(L,R,lson);
if(R>mid) ans+=Query_sum(L,R,rson);
return ans;
} int Query_max(int L,int R,int l,int r,int rt)//寻找L~R的最大值
{
if(L<=l && r<=R) return tree[rt].max_num;
int mid=(l+r)>>;
int ans=-INF;
if(L<=mid) ans=max(ans,Query_max(L,R,lson));
if(R>mid) ans=max(ans,Query_max(L,R,rson));
return ans;
} void addedge(int u,int v)
{
edge[tot].v=v;
edge[tot].nxt=head[u];
head[u]=tot++;
} void dfs1(int u,int father,int depth)
{
fa[u]=father;
dep[u]=depth;
siz[u]=;
for(int i=head[u];~i;i=edge[i].nxt)
{
int v=edge[i].v;
if(v!=fa[u])
{
dfs1(v,u,depth+);
siz[u]+=siz[v];
if(son[u]==- || siz[v]>siz[son[u]]) son[u]=v;
}
}
} void dfs2(int u,int t)
{
top[u]=t;
tid[u]=++cnt; rnk[cnt]=u;//tid[]:表示该点在线段树中的位置/:rnk[]:和tid[]数组相反,根据线段树中的位置,找到树中位置
if(son[u]==-) return ;
dfs2(son[u],t);
for(int i=head[u];~i;i=edge[i].nxt)
{
int v=edge[i].v;
if(v!=son[u] && v!=fa[u]) dfs2(v,v);
}
} int LCA(int u,int v,int flag)//沿着树链求LCA(根据flag的不同,求不同的值)
{
int fu=top[u],fv=top[v],res;
if(flag) res=-INF;// flag=1 求最大值
else res=; //flag=0 求和
while(fu!=fv)
{
if(dep[fu]<dep[fv]) swap(fu,fv),swap(u,v);
if(flag) res=max(res,Query_max(tid[fu],tid[u],,cnt,));
else res+=Query_sum(tid[fu],tid[u],,cnt,);
u=fa[fu],fu=top[u];
}
if(dep[u]>dep[v]) swap(u,v);
if(flag) res=max(res,Query_max(tid[u],tid[v],,cnt,));
else res+=Query_sum(tid[u],tid[v],,cnt,);
return res;
} int main()
{
int n,t,u,v,w;
char op[];
while(~scanf("%d",&n))
{
Init();
for(int i=;i<n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
for(int i=;i<=n;i++) scanf("%d",&a[i]);
dfs1(,,);
dfs2(,);
Build(,cnt,);
scanf("%d",&t);
while(t--)
{
scanf("%s",op);
scanf("%d%d",&u,&v);
if(op[]=='S') printf("%d\n",LCA(u,v,));
else if(op[]=='M') printf("%d\n",LCA(u,v,));
else Update(tid[u],v,,cnt,);
}
}
return ;
}
HYSBZ 1036树链剖分的更多相关文章
- HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分
树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...
- BZOJ 1036 && 树链剖分
还是太弱啊..各种数据结构只听过名字却没有一点概念..树链剖分也在这个范畴..今天来进一步深化一下教育改革推进全民素质提高. 性质 忘了在哪里看到的一篇blog有一句话讲得非常好,树链剖分不是一种数据 ...
- HYSBZ - 2243 树链剖分 + 线段树 处理树上颜色段数
用线段树处理颜色段数 记录区间内的颜色段数,区间右端点的颜色,区间右端点的颜色. int tr[maxn<<2], lc[maxn<<2], rc[maxn<<2] ...
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...
- Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)
Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...
- HYSBZ 1036 【树链剖分】
思路: 裸裸的树链剖分.... 树链剖分就是把一棵树分成若干重链和轻链...然后保证形成的线段树上每条链是连续存储的.然后这样就能用线段树进行维护了. 但是每次一定要保证是在同一条链里边....思路就 ...
- HYSBZ 1036(树链剖分)
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/E 题意:给定一棵树及树上的点权,要求三种操作: 1) ...
- HYSBZ 1036 树的统计Count(树链剖分)题解
思路: 树链剖分,不知道说什么...我连模板都不会用 代码: #include<map> #include<ctime> #include<cmath> #incl ...
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14302 Solved: 5779[Submit ...
随机推荐
- 重写(OverRide)/重载(Overload)
方法的重写规则 参数列表必须完全与被重写方法的相同: 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同): ...
- Unity入门--实用知识
目录 1. VS适配 2.实用快捷操作 3.Unity API文档 4.项目整理 1. VS适配 让你的VS完美支持Unity的脚本编写可以让你写起C#脚本来事半功倍,比如代码补全功能,可以参考下面这 ...
- LeetCode 5264 在受污染的二叉树中查找元素 Find Elements in a Contaminated Binary Tree
地址 https://leetcode-cn.com/contest/weekly-contest-163/problems/find-elements-in-a-contaminated-binar ...
- 网站搭建 - Linux虚拟系统 - 时间设置 - root密码修改 - 建站
先试一下,如果不成的话,就不发表了. 下载织梦: 额,这个先还是不要下了. Linux是Apache + MySQL + PHP的套路,先下载吧,不摆图了,直接摆命令,我的是虚拟机,可能没有那么顺利. ...
- 插入排序的代码实现(C语言)
void insert_sort(int arr[], int len) { for (int i = 1; i < len; ++i) { if (arr[i] < arr[i - 1] ...
- Geometry 判断几何是否被另一个几何/线段分割成多段
如下图,如何判断几何多边形A被多边形B,切割为多段几何? 几何A被几何B切割 1. 获取几何A与几何B的交集C var intersectGeometry = new CombinedGeometry ...
- vue开发之跨域请求,请求头not allowed by Access-Control-Allow-Headers,后端cookie session值取不到(二)
原因:你本地的请求ajax的get和post请求:如果你的请求头内放一些可用验证数据Token的时候就会存在跨域请求这是浏览器所不允许的问题: 方案一:后台的接口请求模式都写成jsonp请求,前端去调 ...
- nyoj 27-水池数目(BFS, DFS)
27-水池数目 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:17 submit:22 题目描述: 南阳理工学院校园里有一些小河和一些湖泊,现在,我 ...
- [FPGA]Verilog实现JK触发器组成的8421BCD码十进制计数器
目录 概述 电路分析 代码实现 参考文献 概述 本文以异步时序计数器为例,用Verilog实现以\(JK\)触发器组成的8421BCD码十进制异步计数器,并用ModelSim软件进行仿真验证. 电路分 ...
- iOS开发调试概览
概述 我们都知道Xcode默认的调试器是LLDB(在此之前使用的是GDB),但是关于LLDB的debug技巧并非所有人都比较清楚,可能所有人都知道p或者po命令打印一些变量.但是实际的情况时这些还远远 ...