[ZJOI2008]树的统计(树链剖分)
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 本身。
输入格式
输入文件的第一行为一个整数 n,表示节点的个数。
接下来 n-1 行,每行 2 个整数 a 和 b,表示节点 a 和节点 b 之间有一条边相连。
接下来一行 n 个整数,第 i 个整数 w_i 表示节点 i 的权值。接下来 1 行,为一个整数 q,表示操作的总数。
接下来 q行,每行一个操作,以 CHANGE u t 或者 QMAX u v 或者 QSUM u v 的形式给出。
输出格式
对于每个 QMAX 或者 QSUM 的操作,每行输出一个整数表示要求输出的结果。
Solution
模板题。。。
Code
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
const int N=3e4+;
vector <int> link[N];
struct node
{
int l,r,lc,rc,sum,ma;
}f[N*];
int fa[N],top[N],son[N],dfn[N],size[N],n,q,a,b,cnt,tot,rt,d[N],deep[N];
char s[];
void dfs1(int u,int fat)
{
size[u]=,fa[u]=fat,deep[u]=deep[fat]+;
int siz=link[u].size();
for(int i=;i<siz;i++)
{
int v=link[u][i];
if(v==fa[u]) continue;
dfs1(v,u),size[u]+=size[v];
if(son[u]== || size[son[u]]<size[v]) son[u]=v;
}
}
void dfs2(int u)
{
dfn[u]=++cnt;
if(son[u])
{
top[son[u]]=top[u],dfs2(son[u]);
int siz=link[u].size();
for(int i=;i<siz;i++)
{
int v=link[u][i];
if(v==fa[u] || v==son[u]) continue;
top[v]=v,dfs2(v);
}
}
}
void push_up(int g)
{
int lc=f[g].lc,rc=f[g].rc;
if(lc==) return ;
f[g].ma=max(f[lc].ma,f[rc].ma);
f[g].sum=f[lc].sum+f[rc].sum;
}
void build(int &g,int l,int r)
{
g=++tot,f[g].l=l,f[g].r=r;
if(l==r)
{
f[g].ma=f[g].sum=d[l];
return ;
}
int mid=(l+r)>>;
build(f[g].lc,l,mid);
build(f[g].rc,mid+,r);
push_up(g);
}
void change(int g,int x,int y)
{
if(f[g].l==f[g].r)
f[g].ma=f[g].sum=y;
else
{
int mid=(f[g].l+f[g].r)>>;
if(x<=mid) change(f[g].lc,x,y);
else change(f[g].rc,x,y);
push_up(g);
}
}
int get_max(int g,int l,int r)
{
if(f[g].l>=l && f[g].r<=r)
return f[g].ma;
else
{
int mid=(f[g].l+f[g].r)>>;
if(r<=mid) return get_max(f[g].lc,l,r);
else if(l>mid) return get_max(f[g].rc,l,r);
else return max(get_max(f[g].lc,l,mid),get_max(f[g].rc,mid+,r));
}
}
int get_sum(int g,int l,int r)
{
if(f[g].l>=l && f[g].r<=r)
return f[g].sum;
else
{
int mid=(f[g].l+f[g].r)>>;
if(r<=mid) return get_sum(f[g].lc,l,r);
else if(l>mid) return get_sum(f[g].rc,l,r);
else return get_sum(f[g].lc,l,mid)+get_sum(f[g].rc,mid+,r);
}
}
int Get_sum(int x,int y)
{
int ans=;
int px=top[x],py=top[y];
while(px!=py)
if(deep[px]>deep[py])
{
ans+=get_sum(rt,dfn[px],dfn[x]);
x=fa[px],px=top[x];
}
else
{
ans+=get_sum(rt,dfn[py],dfn[y]);
y=fa[py],py=top[y];
}
if(dfn[x]<dfn[y]) ans+=get_sum(rt,dfn[x],dfn[y]);
else ans+=get_sum(rt,dfn[y],dfn[x]);
return ans;
}
int Get_max(int x,int y)
{
int ans=-<<;
int px=top[x],py=top[y];
while(px!=py)
if(deep[px]>deep[py])
{
ans=max(ans,get_max(rt,dfn[px],dfn[x]));
x=fa[px],px=top[x];
}
else
{
ans=max(ans,get_max(rt,dfn[py],dfn[y]));
y=fa[py],py=top[y];
}
if(dfn[x]<dfn[y]) ans=max(ans,get_max(rt,dfn[x],dfn[y]));
else ans=max(ans,get_max(rt,dfn[y],dfn[x]));
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d%d",&a,&b);
link[a].push_back(b);
link[b].push_back(a);
}
dfs1(,),top[]=,dfs2();
for(int i=;i<=n;i++)
scanf("%d",&d[dfn[i]]);
build(rt,,cnt);
scanf("%d",&q);
//CHANGE u t :把节点 u权值改为 t;
//QMAX u v :询问点 u到点 v路径上的节点的最大权值;
//QSUM u v :询问点 u到点 v路径上的节点的权值和。
while(q--)
{
scanf("%s",s);
scanf("%d%d",&a,&b);
if(s[]=='C')
change(rt,dfn[a],b);
else if(s[]=='M')
printf("%d\n",Get_max(a,b));
else printf("%d\n",Get_sum(a,b));
}
return ;
}
[ZJOI2008]树的统计(树链剖分)的更多相关文章
- BZOJ 1036: [ZJOI2008]树的统计Count-树链剖分(点权)(单点更新、路径节点最值、路径求和)模板,超级认真写了注释啊啊啊
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 23015 Solved: 9336[Submit ...
- 树的统计Count---树链剖分
NEFU专项训练十和十一——树链剖分 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t ...
- BZOJ1036[ZJOI2008]树的统计——树链剖分+线段树
题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...
- [ZJOI2008]树的统计——树链剖分
本题是一个树链剖分裸题,由于比较菜,老是RE,后来发现是因为使用了全局变量. /************************************************************ ...
- [luogu P2590 ZJOI2008] 树的统计 (树链剖分)
题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u ...
- luoguP2590 [ZJOI2008]树的统计(树链剖分)
luogu P2590 [ZJOI2008]树的统计 题目 #include<iostream> #include<cstdlib> #include<cstdio> ...
- 洛谷P2590 [ZJOI2008] 树的统计 [树链剖分]
题目传送门 树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t ...
- BZOJ 1036 树的统计-树链剖分
[ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...
- BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)
潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...
- bzoj1036 树的统计 树链剖分模板
题意:给出树上任意两点,求路径上的值的和与最大值,带单点修改操作 树链剖分思路: 1.对树进行dfs求出点的深度和父亲节点,然后求出轻重儿子(重儿子就是点最多的那个子树,其余都是轻儿子),用一个son ...
随机推荐
- Struts2 类型转换(易百教程)
在HTTP请求中的一切都被视为一个String由协议.这包括数字,布尔值,整数,日期,小数和一切.每一件事情是一个字符串,将根据HTTP.然而,Struts类可以有任何数据类型的属性.Struts的自 ...
- 记录安装Python第三方包“tesserocr”的方法和遇到的坑
1. 环境: 系统环境:Win7 32 位系统 Python版本: 3.6.5 虚拟环境为:Miniconda3 2. 共需要安装的模块: a. tesserocr b. tessera ...
- ajax异步发送时遇到的问题
问题原因是:controller中方法名与url中的名字不一样造成的 解决办法:找到错误的方法名,将其与url中的方法名统一:
- Joomla 3.9.13 二次注入分析(CVE-2019-19846)
目录 前言 分析 更好的注入 利用 总结 补丁分析 前言 这一个需要管理员权限的二次SQL注入,利用起来比较鸡肋.这里仅分享一下挖洞时的思路,不包含具体的poc. 分析 漏洞触发点在component ...
- CodeForces 1182D
图论的思维题,太秀了,网上答案也不多,我就也来bb吧 总之47个样例姑且是过了,不知道还有没有反例: 会求树的重心和中心了,挺好 #include<cstdio> #include< ...
- flask修改数据库字段的类型和长度
flask修改数据库字段的类型和长度 在将models中的字段的db.String(256)修改为db.String(1024)后,执行migrate和upgrade操作后,发现数据库并没有更新, ...
- 基于ambassador实现K8S灰度发布
为什么需要灰度发布 灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式.在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对 ...
- .NET设计篇08-线程取消模型和跨线程访问UI
知识需要不断积累.总结和沉淀,思考和写作是成长的催化剂,输出倒逼输入 内容目录 一.线程统一取消模型1.取消令牌2.可以中断的线程1.设计一个中断函数2.创建CancellationTokenSour ...
- 浅谈JSON HiJacking攻击
JSON HiJacking攻击: JSON劫持类似于CSRF攻击,为了了解这种攻击方式,我们先看一下Web开发中一种常用的跨域获取数据的方式:JSONP. 先说一下JSON吧,JSON是一种数据格式 ...
- django 数据库连接出现的问题
mysqlclient 1.3.3 or newer is required; you have 0.7.11: 解决方法: 将报错文件中的如下代码注释: if version < (1, 3, ...