题目链接:https://www.luogu.org/problem/P3833

题目大意:有一颗含有n个节点的树,初始时每个节点的值为0,有以下两种操作:

1.Add u v d表示将点u和v之间的路径上的所有节点的值都加上d。

2.Query u表示当前果树中,以点u为根的子树中,总共有多少个果子?

解题思路:树链剖分板子,具体看代码注释

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=;
int tot,cnt,head[maxn],n,m,v[maxn];
ll tree[maxn*],lazy[maxn*];
int d[maxn],size[maxn],son[maxn],id[maxn],rk[maxn],fa[maxn],top[maxn];
//size[i]是i的子树的节点数,top[i]是i所在重链的顶端,son[i]是i的重儿子编号
//d[i]是节点i的真深度,id[i]是i的新编号,fa[i]是i的父亲编号
struct Edge{
int v,next;
}edge[maxn<<];
void add(int u,int v){
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void dfs1(int u,int pre){ //第一遍dfs求每个节点的深度,父亲节点,所在子树大小
d[u]=d[pre]+;
fa[u]=pre;
size[u]=;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].v;
if(v!=pre){
dfs1(v,u);
size[u]+=size[v];
if(size[son[u]]<size[v]) son[u]=v;
}
}
}
void dfs2(int u,int tp){ //求每个节点新编号和重儿子和所在重链顶端
top[u]=tp,id[u]=++cnt,rk[cnt]=u;
if(son[u]) dfs2(son[u],tp);
//先跑重儿子节点保证一条重链上各个节点dfs序连续,以便可以通过线段树来维护一条重链的信息
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].v;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
void pushup(int rt){
tree[rt]=tree[rt<<]+tree[rt<<|];
}
void pushdown(int l,int r,int rt){
if(lazy[rt]){
tree[rt<<]=tree[rt<<]+lazy[rt]*l;
tree[rt<<|]=tree[rt<<|]+lazy[rt]*r;
lazy[rt<<]+=lazy[rt];
lazy[rt<<|]+=lazy[rt];
lazy[rt]=;
}
}
void build(int l,int r,int rt){
lazy[rt]=;
if(l==r){
tree[rt]=v[rk[l]];
return;
}
int mid=l+r>>;
build(l,mid,rt<<);
build(mid+,r,rt<<|);
pushup(rt);
}
void update(int L,int R,int val,int l,int r,int rt){
if(L<=l&&R>=r){
tree[rt]+=1ll*(r-l+)*val;
lazy[rt]+=val;
return;
}
int mid=l+r>>;
pushdown(mid-l+,r-mid,rt);
if(mid>=L) update(L,R,val,l,mid,rt<<);
if(mid<R) update(L,R,val,mid+,r,rt<<|);
pushup(rt);
}
ll query(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r) return tree[rt];
int mid=l+r>>; ll res=;
pushdown(mid-l+,r-mid,rt);
if(mid>=L) res+=query(L,R,l,mid,rt<<);
if(mid<R) res+=query(L,R,mid+,r,rt<<|);
return res;
}
void updates(int x,int y,int val){ //修改x到y最短路径的值
while(top[x]!=top[y]){ //不在同一条重链就向上跳
if(d[top[x]]<d[top[y]]) swap(x,y);
update(id[top[x]],id[x],val,,n,);
x=fa[top[x]]; //跳到该重链顶节点的父节点
}
if(id[x]>id[y]) swap(x,y); //两个节点在同一条重链,但可能不是同一个节点
update(id[x],id[y],val,,n,);
}
ll ask(int x,int y){ //询问x到y最短路径的值
ll res=;
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
res+=query(id[top[x]],id[x],,n,);
x=fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
res+=query(id[x],id[y],,n,);
return res;
}
int main(){
scanf("%d",&n);
memset(head,-,sizeof(head));
for(int i=;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
u++; v++;
add(u,v);
}
scanf("%d",&m);
cnt=,tot=;
dfs1(,),dfs2(,);
build(,n,);
while(m--){
char op[];
int l,r,rt,val;
scanf("%s",op);
if(op[]=='A'){
scanf("%d%d%d",&l,&r,&val);
l++; r++;
updates(l,r,val);
} else{
scanf("%d",&rt); rt++;
printf("%lld\n",query(id[rt],id[rt]+size[rt]-,,n,));
//因为一个子树的大小是size[rt],起点编号是从id[rt]所以是从id[rt]到id[rt]+size[rt]-1
}
}
return ;
}

P3833 [SHOI2012]魔法树 (树链剖分模板题)的更多相关文章

  1. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  2. bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题

    [ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...

  3. BZOJ 1036 树的统计Count 树链剖分模板题

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1036 题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将 ...

  4. 洛谷 P3384 树链剖分(模板题)

    题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...

  5. 【BZOJ 1036】【ZJOI 2008】树的统计 树链剖分模板题

    sth神犇的模板: //bzoj1036 题目:一个n个点的树每个点有一个权值,支持修改单点权值,求某两点路径上的点权和或最大点权. #include <cstdio> using nam ...

  6. 洛谷 P2146 [NOI2015]软件包管理器 (树链剖分模板题)

    题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个 ...

  7. spoj - Grass Planting(树链剖分模板题)

    Grass Planting 题意 给出一棵树,树有边权.每次给出节点 (u, v) ,有两种操作:1. 把 u 到 v 路径上所有边的权值加 1.2. 查询 u 到 v 的权值之和. 分析 如果这些 ...

  8. SPOJ QTREE Query on a Tree【树链剖分模板题】

    树链剖分,线段树维护~ #include <cstdio> #include <cstring> #include <iostream> #include < ...

  9. BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14982  Solved: 6081[Submit ...

随机推荐

  1. 原型模式故事链(4)--JS执行上下文、变量提升、函数声明

    上一章:JS的数据类型 传送门:https://segmentfault.com/a/11... 好!话不多少,我们就开始吧.对变量提升和函数声明的理解,能让你更清楚容易的理解,为什么你的程序报错了~ ...

  2. c/c++运算符

    1.算术运算符(+  -  /  *  %) 2.移位运算符 移运算符:操作数必须是整形,>>,逻辑左移左边移入的位用0填充,算数左移左边移入的的位用符号位补齐.(无符号数为逻辑左移,对于 ...

  3. 当出现no changes added to commit时如何正确使用git提交命令

    对于这个问题,最好的解决方法就是按如下步骤:1.到根目录下:git add .  :("."是必须要的)2.git commit -m "some word"3 ...

  4. MyBaits动态sql语句

    1 在接口中书写方法 public interface EmployeeMapperDynamicSQL { public List<Employee> getEmpsTestInnerP ...

  5. centOS7杀死进程命令

    查看当前所有正在运行的进程,可以看到80端口被httpd占用了(80端口希望分配给nginx使用,而不是httpd) netstat -tpnul 这里以杀死httpd进程为例: 先查看 httpd ...

  6. db4o发布7.2,出现.NET 3.5版本,支持LINQ

    db4o发布7.2,出现.NET 3.5版本,支持LINQ   Db4Object刚刚发布了db4o的7.2beta,除了以前支持如下的平台:.NET 1.1,.NET 2.0,Mono外,现在还支持 ...

  7. 【MM系列】SAP 物料进销存报表查看

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]在SAP里查看数据的方法   前言部 ...

  8. Hello World!----html

    ​ 最近要做一个小网站,今晚想起来还是先看看前端终于抑制住惰性,开始看了. ​ 看了一下html,写了个hello world.老实讲,我竟然还有些小激动 ​ <html> <hea ...

  9. 【Qt开发】Qt在Windows下的三种编程环境搭建

    从QT官网可以得知其支持的平台.编译器和调试器的信息如图所示: http://qt-project.org/doc/qtcreator-3.0/creator-debugger-engines.htm ...

  10. 推荐Calendar操作日期

    package com.example.demo.Calender; import java.text.SimpleDateFormat;import java.util.Calendar;impor ...