洛谷 P3833 [SHOI2012]魔法树
题目背景
SHOI2012 D2T3
题目描述
Harry Potter 新学了一种魔法:可以让改变树上的果子个数。满心欢喜的他找到了一个巨大的果树,来试验他的新法术。
这棵果树共有N个节点,其中节点0是根节点,每个节点u的父亲记为fa[u],保证有fa[u] < u。初始时,这棵果树上的果子都被 Dumbledore 用魔法清除掉了,所以这个果树的每个节点上都没有果子(即0个果子)。
不幸的是,Harry 的法术学得不到位,只能对树上一段路径的节点上的果子个数统一增加一定的数量。也就是说,Harry 的魔法可以这样描述:
Add u v d
表示将点u和v之间的路径上的所有节点的果子个数都加上d。
接下来,为了方便检验 Harry 的魔法是否成功,你需要告诉他在释放魔法的过程中的一些有关果树的信息:
Query u
表示当前果树中,以点u为根的子树中,总共有多少个果子?
输入输出格式
输入格式:
第一行一个正整数N (1 ≤ N ≤ 100000),表示果树的节点总数,节点以0,1,…,N − 1标号,0一定代表根节点。
接下来N − 1行,每行两个整数a,b (0 ≤ a < b < N),表示a是b的父亲。
接下来是一个正整数Q(1 ≤ ? ≤ 100000),表示共有Q次操作。
后面跟着Q行,每行是以下两种中的一种:
A u v d,表示将u到v的路径上的所有节点的果子数加上d;0 ≤ u,v <N,0 < d < 100000
Q u,表示询问以u为根的子树中的总果子数,注意是包括u本身的。
输出格式:
对于所有的Query操作,依次输出询问的答案,每行一个。答案可能会超过2^32 ,但不会超过10^15 。
输入输出样例
3
3
2 题解:
树链剖分的板子好久没打了,写一写。
代码:
// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#define MAXN 400100
#define ll long long
using namespace std;
struct edge{
int first;
int next;
int to;
}a[MAXN*];
struct tree{
int l,r;ll sum,lz;
}tr[MAXN*]; int num,n;
int dep[MAXN],sz[MAXN],id[MAXN],son[MAXN],tp[MAXN],dfn[MAXN],las[MAXN],fa[MAXN]; void addedge(int from,int to){
a[++num].to=to;
a[num].next=a[from].first;
a[from].first=num;
} void dfs1(int now,int f){
fa[now]=f,sz[now]=,dep[now]=dep[f]+;
for(int i=a[now].first;i;i=a[i].next){
int to=a[i].to;
if(to==f) continue;
dfs1(to,now);
sz[now]+=sz[to];
if(sz[son[now]]<sz[to]) son[now]=to;
}
} void dfs2(int now,int top){
dfn[now]=++num;
tp[now]=top;
if(son[now]) dfs2(son[now],top);
for(int i=a[now].first;i;i=a[i].next){
int to=a[i].to;if(to==fa[now]||to==son[now]) continue;
dfs2(to,to);
}
las[now]=num;
} void pushdown(int xv){
int ls=*xv,rs=*xv+;
if(tr[xv].lz){
tr[ls].sum+=(tr[ls].r-tr[ls].l+)*tr[xv].lz;
tr[rs].sum+=(tr[rs].r-tr[rs].l+)*tr[xv].lz;
tr[ls].lz+=tr[xv].lz,tr[rs].lz+=tr[xv].lz;
tr[xv].lz=;
}
} void pushup(int xv){
tr[xv].sum=tr[xv*].sum+tr[xv*+].sum;
} void build(int xv,int l,int r){
if(l==r){
tr[xv].l=l,tr[xv].r=r,tr[xv].sum=,tr[xv].lz=;
return;
}
tr[xv].l=l,tr[xv].r=r,tr[xv].sum=,tr[xv].lz=;
int mid=(l+r)/;
build(xv*,l,mid),build(xv*+,mid+,r);
} void modify(int xv,int l,int r,int z){
int L=tr[xv].l,R=tr[xv].r,mid=(L+R)/;
if(L==l&&R==r){
tr[xv].sum+=z*(R-L+);
tr[xv].lz+=z;
return;
}
pushdown(xv);
if(r<=mid) modify(xv*,l,r,z);
else if(l>mid) modify(xv*+,l,r,z);
else modify(xv*,l,mid,z),modify(xv*+,mid+,r,z);
pushup(xv);
} ll query(int xv,int l,int r){
int L=tr[xv].l,R=tr[xv].r,mid=(L+R)/;
if(L==l&&R==r) return tr[xv].sum;
pushdown(xv);
if(r<=mid) return query(xv*,l,r);
else if(l>mid) return query(xv*+,l,r);
else return query(xv*,l,mid)+query(xv*+,mid+,r);
} void add(int x,int y,int z){
int topx=tp[x],topy=tp[y];
while(topx!=topy){
if(dep[topx]<dep[topy]) swap(x,y),swap(topx,topy);
modify(,dfn[topx],dfn[x],z);
x=fa[topx];topx=tp[x];
}
if(dep[x]<dep[y]) swap(x,y);
modify(,dfn[y],dfn[x],z);
} int main()
{
scanf("%d",&n);
for(int i=;i<n;i++){
int x,y;scanf("%d%d",&x,&y);
x++,y++;
addedge(x,y),addedge(y,x);
}
dfs1(,);num=;
dfs2(,);fa[]=;
build(,,n);
int q;cin>>q;
while(q--){
char id;cin>>id;
if(id=='A'){
int x,y,z;scanf("%d%d%d",&x,&y,&z);x++,y++;
add(x,y,z);
}
else{
int x;scanf("%d",&x);x++;
printf("%lld\n",query(,dfn[x],las[x]));
}
}
return ;
}
洛谷 P3833 [SHOI2012]魔法树的更多相关文章
- 洛谷——P3833 [SHOI2012]魔法树
P3833 [SHOI2012]魔法树 题目背景 SHOI2012 D2T3 题目描述 Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的 ...
- [洛谷P3833][SHOI2012]魔法树
题目大意:给一棵树,路径加,子树求和 题解:树剖 卡点:无 C++ Code: #include <cstdio> #include <iostream> #define ma ...
- 洛谷3833 [SHOI2012]魔法树
SHOI2012 D2T3 题目描述 Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的新法术. 这棵果树共有N个节点,其中节点0是根节点 ...
- P3833 [SHOI2012]魔法树
思路 树剖板子 注意给出点的编号是从零开始的 代码 #include <cstdio> #include <algorithm> #include <cstring> ...
- 洛谷P3833 [SHOI2012]魔法树(树链剖分)
传送门 树剖板子…… 一个路径加和,线段树上打标记.一个子树询问,dfs的时候记录一下子树的区间就行 // luogu-judger-enable-o2 //minamoto #include< ...
- [SHOI2012]魔法树
题目:洛谷P3833. 题目大意:给你一棵树,有两种操作:1.给两个点和它们之间的最短路上的所有点加上一个值:2.询问以某个点为根的子树的子树和.你需要实现这个功能. 解题思路:如果只有最后才询问的话 ...
- 树链剖分【洛谷P3833】 [SHOI2012]魔法树
P3833 [SHOI2012]魔法树 题目描述 Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的新法术. 这棵果树共有N个节点,其中节 ...
- 树链剖分【P3833】 [SHOI2012]魔法树
Description Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的新法术. 这棵果树共有N个节点,其中节点0是根节点,每个节点u的 ...
- 题解 P3833 【[SHOI2012]魔法树】
题目 直通车 很显然这是个树刨的板子,树上链查询和子树查询 注意: 1.这个点的树根为 0 而不是 1 所以注意读图时点标号 +1 就解决了 2.注意数据范围\(2^{32}\) 然后板子就能过了 n ...
随机推荐
- Redis哨兵模式实现集群的高可用
先了解一下哨兵都 做了什么工作:Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务: 监控(Monitoring): Sentinel ...
- Visual Studio 调试 —— 附加到进程(远程服务器)
一般在部署环境下不会有 Visual Studio 开发工具的,所以需要有 Remote Debugger(远程调试器) 才可以进行远程调试. Remote Debugger 获取 方法一:Visua ...
- linux ubuntu 18首次使用root权限
第一次获得root密码: sudo passwd root 切换成root用户,获得root权限 exit 退出,回到初始用户
- Vue中的slot(占坑,预留位置)
Vue中的slot(占坑,预留位置) 子模板不使用slot 子模板使用slot 子模板使用使用name属性,且传递data 文件名:Slots.vue //slot组件 <template> ...
- Unity3D_03_代码及效率优化总结
1.在使用数组或ArrayList对象时应当注意: length = myArray.Length; ;i<length;i++) { } 避免 ;i<myArray.Length;i++ ...
- hadoop snapshot 备份恢复 .
1.允许创建快照 首先,在你想要进行备份的文件夹下面 执行命令,允许该文件夹创建快照 hdfs dfsadmin -allowSnapshot <path> 例如:hdfs dfsadmi ...
- Hadoop学习笔记之HBase Shell语法练习
Hadoop学习笔记之HBase Shell语法练习 作者:hugengyong 下面我们看看HBase Shell的一些基本操作命令,我列出了几个常用的HBase Shell命令,如下: 名称 命令 ...
- 【学习笔记】python3核心技术与实践--如何逐步突破,成为python高手
众所周知,Facebook 的主流语言是 Hack(PHP 的进化版本).不过,我敢拍着胸脯说,就刚入职的工程师而言,100 个里至少有 95 个,以前都从未用过 Hack 或者 PHP.但是,这些人 ...
- Spring事务传播行为中可能的坑点
一.简介 Spring事务配置及相关说明详见:https://www.cnblogs.com/eric-fang/p/11052304.html.这里说明spring事务的几点注意: 1.默认只会检查 ...
- Spring Boot 配置元数据指南
1. 概览 在编写 Spring Boot 应用程序时,将配置属性映射到 Java bean 上是非常有用的.但是,记录这些属性的最好方法是什么呢? 在本教程中,我们将探讨 Spring Boot C ...