BZOJ 1036: [ZJOI2008]树的统计Count 【树链剖分】
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. 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
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
1
2
2
10
6
5
6
5
16
HINT
Source
思路:唔说是树分治,其实裸的树链剖分,这里总结一下树链剖分吧,基本思路就是把树上的路径分成两种,一般是轻重链剖分,然后重链在线段树上查,轻链直接向父亲条的做法,当然由于它们同时存在于线段树中,所以两步是可以合并的,树剖的思想大概就是这样,用到的数组也就是father[]记录父亲,top[]记录重链顶部的节点,id[]记录每个节点在线段树中的位置三个而已,至于其它像size,son之类的只是为了求出前面三个数组所开的辅助数组,一般的话第一个dfs找重儿子,重边,第二个dfs将前面找到的重边连起来变成重链求出top
#include<iostream>
#include<cstdio>
#define maxn 60000
using namespace std;
int w[maxn],head[maxn],point[maxn],next[maxn*],top[maxn],id[maxn],size_k[maxn],pos=,now;
int father[maxn],son[maxn],deep[maxn];
struct T
{
int max_x;int sum_x;
T(){max_x=-0x3f3f3f3f;sum_x=;}
}tree[maxn*];
T work(T x,T y)
{
T ans;
ans.max_x=max(x.max_x,y.max_x);
ans.sum_x=x.sum_x+y.sum_x;
return ans;
}
T query(int node,int l,int r,int ql,int qr)
{
if(ql<=l && r<=qr)return tree[node];
int mid=(l+r)>>;T ans;
if(ql<mid)ans=query(node*,l,mid,ql,qr);
if(mid<qr)ans=work(ans,query(node*+,mid,r,ql,qr));
return ans;
}
void update(int node,int l,int r,int p,int x){
if(l+==r){
tree[node].max_x=x;tree[node].sum_x=x;return ;
}
int mid=(l+r)>>;
if(p<mid)update(node*,l,mid,p,x);
else update(node*+,mid,r,p,x);
tree[node]=work(tree[node*],tree[node*+]);
return ;
}
void add(int x,int y){
next[++now]=head[x];head[x]=now;point[now]=y;
}
void dfs(int k,int fa)
{
deep[k]=deep[fa]+;
father[k]=fa;size_k[k]=;
int max_x=-;son[k]=-;
for(int i=head[k];i;i=next[i])
{
if(point[i]==fa)continue;
dfs(point[i],k);
size_k[k]+=size_k[point[i]];
if(size_k[point[i]]>max_x)
{
max_x=size_k[point[i]];
son[k]=point[i];
}
}
}
void dfs2(int k,int fa,int pa)
{
id[k]=++pos;top[k]=pa;
if(son[k]!=-)dfs2(son[k],k,pa);
for(int i=head[k];i;i=next[i])if(point[i]!=fa && point[i]!=son[k])dfs2(point[i],k,point[i]); }
T find(int x,int y)
{
int fx=top[x],fy=top[y];
T tmp;
while(fx!=fy)
{
if(deep[fx]<deep[fy])swap(fx,fy),swap(x,y);
tmp=work(tmp,query(,,pos+,id[fx],id[x]+));
x=father[fx];fx=top[x];
}
if(deep[x]<deep[y])swap(x,y);
return work(tmp,query(,,pos+,id[y],id[x]+));
}
int main()
{
int n,x,y,q;
char ch[];
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
for(int i=;i<=n;i++)scanf("%d",&w[i]);
scanf("%d",&q);
dfs(,);dfs2(,,);
for(int i=;i<=n;i++)update(,,pos+,id[i],w[i]); while(q--)
{
scanf("%s%d%d",ch,&x,&y);
if(ch[]=='S')
{
T u=find(x,y);printf("%d\n",u.sum_x);
}
if(ch[]=='M')
{
T u=find(x,y);printf("%d\n",u.max_x);
}
if(ch[]=='H')update(,,pos+,id[x],y);
}
return ;
}
BZOJ 1036: [ZJOI2008]树的统计Count 【树链剖分】的更多相关文章
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14302 Solved: 5779[Submit ...
- Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 11102 Solved: 4490[Submit ...
- BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )
树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...
- bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 16294 Solved: 6645[Submit ...
- BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14982 Solved: 6081[Submit ...
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分)(线段树单点修改)
[ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14968 Solved: 6079[Submit][Stat ...
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
[BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ...
- bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题
[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...
- Cogs 1688. [ZJOI2008]树的统计Count(树链剖分+线段树||LCT)
[ZJOI2008]树的统计Count ★★★ 输入文件:bzoj_1036.in 输出文件:bzoj_1036.out 简单对比 时间限制:5 s 内存限制:162 MB [题目描述] 一棵树上有n ...
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...
随机推荐
- Linux下各文件夹的结构说明及用途介绍(转载)
linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录 ...
- 创建一个文件夹用于写入UTF-8编码的文件
实现效果: 知识运用: File类的CreateText方法 StreamWriter类的WriteLine方法 实现代码: private void button2_Click(object sen ...
- 阿里Java架构师面试高频300题:集合+JVM+Redis+并发+算法+框架等
前言 在过2个月即将进入9月了,然而面对今年的大环境而言,跳槽成功的难度比往年高了很多,很明显的感受就是:对于今年的java开发朋友跳槽面试,无论一面还是二面,都开始考验一个Java程序员的技术功底和 ...
- 树状数组 简单题 cf 961E
题目链接 : https://codeforces.com/problemset/problem/961/E One day Polycarp decided to rewatch his absol ...
- QT +样式表
学习样式表的目的:可以设计出好看的控件.(比如可以给一些按钮设计成好看的图片) QT 样式表的思想很大程度上是来自于HTML的层叠式样式表(CSS),通过调用QWidget->setStyleS ...
- 基于PassThru的NDIS中间层驱动程序扩展
基于PassThru的NDIS中间层驱动程序扩展 独孤求真 概要:开发一个NDIS驱动是一项相对复杂的工作,这一方面是由于核心驱动本身 ...
- ios坐标系统
在写程序的时候发现,iOS下的坐标.位置很容易弄乱,特别是在不同的坐标系统中,必须完成弄明白一些概念才能做相应的变化,例如CoreImage和UIView的坐标系统就截然不同,一个是以屏幕的左上角为原 ...
- 前端上传控件plupload总结
plupload是一个单图和多图上传控件: 属性和方法介绍,参考以下博客: https://www.cnblogs.com/2050/p/3913184.html 这里直接贴出JS代码,细到爆的注释, ...
- MySQL中常见的锁
一.按读写方式分类 1.读锁又称共享锁,读锁是共享的,读锁之间是互不阻塞. 2.写锁又称排他锁,写锁是排他的,写锁会阻塞其他读锁和写锁 二.按锁的粒度分类 1.表锁是MySQL中最基本的锁策略,该锁的 ...
- GIMP里的Path移动,旋转,翻转操作
1/Path的移动: 快捷键Ctrl+Move Tool 2/Path的旋转: 选择Rotate Tool,在Path中选择,出现十字圈. Angel下的滑块调节一定的角度,在合适的位置即可. 3/P ...