洛谷 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 ...
随机推荐
- .gitignore文件失效的解决方案
通常在idea中,我们使用git进行项目管理的时候,一些不需要的文件如.idea,.target文件不需要上传至gitlab仓库,这时,就需要在项目中定义一个.gitignore文件,用来标识这些文件 ...
- 【Redis】哨兵机制
一.概述 什么是哨兵机制 二.环境配置 2.1 虚拟机 2.2 安装Redis 2.3 配置主从复制 2.4 配置哨兵 2.5 测试 2.6 疑惑(待解决) 一.概述 什么是哨兵机制 Redis的哨兵 ...
- Python网络爬虫实战(一)快速入门
本系列从零开始阐述如何编写Python网络爬虫,以及网络爬虫中容易遇到的问题,比如具有反爬,加密的网站,还有爬虫拿不到数据,以及登录验证等问题,会伴随大量网站的爬虫实战来进行. 我们编写网络爬虫最主要 ...
- 阿里第二轮面试:手写Java二叉树
阿里面试 现在很多公司在招聘开发岗位的时候,都会事先在招聘信息中注明面试者应当具备的知识技能,而且在面试的过程中,有部分对于技能掌握程度有严格要求的公司还会要求面试者手写代码,这个环节很考验面试者的基 ...
- Java中的java.lang.Class API 详解
且将新火试新茶,诗酒趁年华. 概述 Class是一个位于java.lang包下面的一个类,在Java中每个类实例都有对应的Class对象.类对象是由Java虚拟机(JVM)自动构造的. Class类的 ...
- 阿里云 centos7 64位搭建JAVA环境-----安装JDK(2)
mysql安装好以后,把jdk环境配置一下. 首先下载jdk 8,在官网下载. 找到链接 http://download.oracle.com/otn-pub/java/jdk/8u171-b11/5 ...
- Fliptile(枚举+DFS)
Problem Description Farmer John knows that an intellectually satisfied cow is a happy cow who will g ...
- Python基础(十)
今日主要内容 补充:传参与参数分配区别 动态传参 函数注释 名称空间 函数名的使用 函数嵌套 global和nonlocal 补充:传参与参数分配区分 先看一个函数定义和函数调用 def func(a ...
- C++解决最基本的迷宫问题
问题描述:给定一个最基本的迷宫图,用一个数组表示,值0表示有路,1表示有障碍物,找一条,从矩阵的左上角,到右下角的最短路.求最短路,大家最先想到的可能是用BFS求,本文也是BFS求最短路的. 源代码如 ...
- 04 (H5*) Vue第四天
目录: 1:父组件向子组件传值,通过属性绑定的方式. 2:父组件向子组件传方法,通过事件绑定的方式 . 3:通过ref来获取Dom元素 1:父组件向子组件传值,通过属性绑定的方式 1.1:父组件声明数 ...