题目背景

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行,每行是以下两种中的一种:

  1. A u v d,表示将u到v的路径上的所有节点的果子数加上d;0 ≤ u,v <N,0 < d < 100000

  2. Q u,表示询问以u为根的子树中的总果子数,注意是包括u本身的。

输出格式:

对于所有的Query操作,依次输出询问的答案,每行一个。答案可能会超过2^32 ,但不会超过10^15 。

输入输出样例

输入样例#1:
复制

4
0 1
1 2
2 3
4
A 1 3 1
Q 0
Q 1
Q 2
输出样例#1: 复制

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]魔法树的更多相关文章

  1. 洛谷——P3833 [SHOI2012]魔法树

    P3833 [SHOI2012]魔法树 题目背景 SHOI2012 D2T3 题目描述 Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的 ...

  2. [洛谷P3833][SHOI2012]魔法树

    题目大意:给一棵树,路径加,子树求和 题解:树剖 卡点:无 C++ Code: #include <cstdio> #include <iostream> #define ma ...

  3. 洛谷3833 [SHOI2012]魔法树

    SHOI2012 D2T3 题目描述 Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的新法术. 这棵果树共有N个节点,其中节点0是根节点 ...

  4. P3833 [SHOI2012]魔法树

    思路 树剖板子 注意给出点的编号是从零开始的 代码 #include <cstdio> #include <algorithm> #include <cstring> ...

  5. 洛谷P3833 [SHOI2012]魔法树(树链剖分)

    传送门 树剖板子…… 一个路径加和,线段树上打标记.一个子树询问,dfs的时候记录一下子树的区间就行 // luogu-judger-enable-o2 //minamoto #include< ...

  6. [SHOI2012]魔法树

    题目:洛谷P3833. 题目大意:给你一棵树,有两种操作:1.给两个点和它们之间的最短路上的所有点加上一个值:2.询问以某个点为根的子树的子树和.你需要实现这个功能. 解题思路:如果只有最后才询问的话 ...

  7. 树链剖分【洛谷P3833】 [SHOI2012]魔法树

    P3833 [SHOI2012]魔法树 题目描述 Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的新法术. 这棵果树共有N个节点,其中节 ...

  8. 树链剖分【P3833】 [SHOI2012]魔法树

    Description Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的新法术. 这棵果树共有N个节点,其中节点0是根节点,每个节点u的 ...

  9. 题解 P3833 【[SHOI2012]魔法树】

    题目 直通车 很显然这是个树刨的板子,树上链查询和子树查询 注意: 1.这个点的树根为 0 而不是 1 所以注意读图时点标号 +1 就解决了 2.注意数据范围\(2^{32}\) 然后板子就能过了 n ...

随机推荐

  1. Spring Cloud官方文档中文版-服务发现:Eureka客户端

    官方文档地址为:http://cloud.spring.io/spring-cloud-static/Dalston.SR2/#_spring_cloud_netflix 文中例子我做了一些测试在:h ...

  2. 我真的不想再用 JPA 了

    在开发者的圈子里,没当说到一种技术好或者不好,都会引发激烈或者不激烈的争论,直到一个开发者出来说 PHP 是世界上最好的语言,大家伙儿才会纷纷退去继续写代码. 今天说 JPA 的问题不是想引发什么讨论 ...

  3. git之rebase、merge和cherry pick的区别(面试常问)

    git flow图例镇楼 merge 这个简单,初学者常用.比如主分支是Dev,最新版本是01.然后小明基于此,搞了个feature 分支A,业务:打酱油.然后在上面多次提交,完成功能迭代开发,如A1 ...

  4. 一文轻松搞懂Vuex

    概念: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式(官网地址:https://vuex.vuejs.org/zh/).它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状 ...

  5. Docker详解(三)

    目录 1. Docker镜像 1.1 镜像存储 1.2 base镜像 1.3 镜像Commit 2. Docker容器数据卷 2.1 基本介绍 2.2 数据卷 2.3 数据卷容器 序言:前两章我们主要 ...

  6. Nginx--面试基础必会

    文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 最近一直在更新关于Nginx的系列文章,终于将Nginx的几个关键知识点讲的差不多了.本篇作为Nginx系列的 ...

  7. js vue 页面添加水印

    vue 微信页面添加水印 this.$nextTick(function() {                                   watermark({ watermark_txt ...

  8. mysql-connector-java-5.-bin.jar 下载方法

    访问https://downloads.mysql.com/archives/c-j/,选择相应版本,如图 加油zip即可得到

  9. [C++] C++中的宏定义详解

    转载自:C++中的宏定义 和 C++宏定义详解 一.#define解析     #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率 ...

  10. Python必备收藏!Pycharm 常用快捷键思维导图!

    本内容首发公众号[计算机视觉联盟],关注获取更多资料! 考虑到可能图片压缩,将思维导图的pdf和jpg版本都上传了百度云,大家可以下载打印一张A4纸,方便查询! 公众号后台回复关键词: 2019082 ...