题目链接: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. python基础之 数据格式化

    %还是format 皇城PK Python中格式化字符串目前有两种阵营:%和format,我们应该选择哪种呢? 自从Python2.6引入了format这个格式化字符串的方法之后,我认为%还是form ...

  2. 48 条高效率的 PHP 优化写法

    来源:歪麦博客 https://www.awaimai.com/1050.html 1 字符串 1.1 少用正则表达式 能用PHP内部字符串操作函数的情况下,尽量用他们,不要用正则表达式, 因为其效率 ...

  3. mysql高水位问题解决办法

    数据库中有些表使用delete删除了一些行后,发现空间并未释放产生原因:类比Oracle的高水位线产生原理 delete 不会释放文件高水位 truncate会释放 ,实际是把.ibd文件删掉了,再建 ...

  4. CentOS7配置静态IP中NM_CONTROLLED不要设置为NO

    这个是网络管理的,之前一直是把这个选项设置为NO,然后在CentOS其中,每次重启网络服务都会失败,后来把这个设为YES就可以了.

  5. CentOS7 nginx安装与卸载

    简明清晰,易操作,参照: CentOS7 nginx安装与卸载

  6. Linux_OpenSSH远程连接

    目录 目录 SSH server SSH服务属性 SSH协议执行原理 SSH连接方式 ssh Commands scp commands sftp commands SSH在生产环境中的使用 系统间备 ...

  7. python学习笔记:(八)条件语句

    if语句,python中if语句的一般形式如下: conditon1为真,执行statement_block_1 condition1为假,判断conition_2,如果condition_2为真,执 ...

  8. Python学习之==>文件操作

    1.打开文件的模式 r,只读模式(默认)[不可写:文件不存在,会报错] w,只写模式[不可读:不存在则创建:存在则删除内容] a,追加模式[不可读:不存在则创建:存在则追加内容] r+,读写模式[可读 ...

  9. CDS究竟是个什么鬼?它直接导致了次贷危机?

    周五,中国银行间市场交易商协会就确认了这一消息,信用违约互换(CDS)和信用联结票据(CLN)业务指引在今日正式发布实行. 当然,这则消息在中国普通投资者当中还没引起足够关注,但是在很多人看来CDS这 ...

  10. CF 686D. Kay and Snowflake

    给你一个树N个点,再给出Q个询问,问以x为根的子树中,重心是哪个?2≤n≤300000,1≤q≤30000 Sol:从下到上,根据性质做一下.1:如果某个点x,其子树y的大小超过总结点个数一半,则重心 ...