[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 ...
随机推荐
- C# 实现多线程
1.System.Threading命名空间 System.Threading命名空间提供了使得可以多线程编程的类和接口 其中 (1)Thread类构成了C#多线程编程的支柱,他用于创建并控制线程 ...
- 数据预处理以及探索性分析(EDA)
1.根据某个列进行groupby,判断是否存在重复列. # Count the unique variables (if we got different weight values, # for e ...
- Cortex-A8/A76
Cortex-A8 关于Cortex-A8的微处理架构参考<ARM_Cortex-A8微处理器的架构和实现> 其中关于NEON有两段话摘录如下: NEON媒体引擎拥有自己的10段流水线,它 ...
- stm32外部时钟源8M换成12M后库函数相应修改总结
前言 在做“自制继电器上位机控制软件”项目的时候,下位机用到USB虚拟串口,将以前写好的USB虚拟串口程序移植到下位机,发现程序计算机无法识别到虚拟串口STMicroelectronics Virtu ...
- acwing 239. 奇偶游戏 并查集
地址 https://www.acwing.com/problem/content/241/ 小A和小B在玩一个游戏. 首先,小A写了一个由0和1组成的序列S,长度为N. 然后,小B向小A提出了M个 ...
- Typescript 最佳实践
文章列表: <一>大话 TypeScript 基本类型 <二>大话 Typescript 枚举 <三>大话 Typescript 接口 <四>大话 Ty ...
- Java_地铁购票系统
定义了两个类,在Subway类中定义三个私有数据变量,线路号,经过站点,换乘站.以及4个方法分别实现从txt文件中导入线路信息:输出线路信息:查询两个站点经过站点数,并输出经过站点以及在某站换乘几号线 ...
- 第 426 期 Python 周刊
文章,教程和讲座 端到端机器学习:从数据收集到模型部署 链接: https://ahmedbesbes.com/end-to-end-ml.html 在本文中,我们将完成构建和部署机器学习应用程序的必 ...
- Ural1057. Amount of Degrees 题解 数位DP
题目链接: (请自行百度进Ural然后查看题号为1057的那道题目囧~) 题目大意: Create a code to determine the amount of integers, lying ...
- NSOperationQueue队列依赖相关思考
添加依赖后,队列中网络请求任务有依赖关系时,任务结束判定以数据返回为准还是以发起请求为准? waitUntilFinished方法容易误解. 依赖关系 // // ViewController.m / ...