Harry Potter新学了一种魔法:可以改变树上的果子个数。满心欢喜的他找到了一个巨大的果树,来试验他的新法
术。这棵果树共有N个节点,其中节点0是根节点,每个节点u的父亲记为fa[u],保证有fa[u]<u。初始时,这棵果
树上的果子都被Dumbledore用魔法清除掉了,所以这个果树的每个节点都没有果子(即0个果子)不幸的是,Harry
的法术学得不到位,只能对树上一段路径的节点上的果子个数统一增加一定的数量。也就是说,Harry的魔法可以
这样描述:Add u v d,表示将节点u和v之间的路径上的所有节点的果子个数都加上d。接下来,为了方便检验Harr
y的魔法是否成功,你需要告诉他在释放魔法的过程中的一些有关果树的信息:Query u,表示当前果树中,以点u
为根的子树中,总共有多少个果子?
Input
第一行一个整数N(1≤N≤100000),表示果树的节点总数,节点以0,1,...,N-1标号,0一定代表根节点。
接下来N-1行,每行两个整数a,b(0≤a接下来是一个整数Q(1≤Q≤100000),表示共有Q次操作。
后面跟着Q行,每行是以下两种中的一种:
1. A u v d,表示将u到v的路径上的所有节点的果子数加上d;(0≤u,v≤N-1,0<d<100000)
2. Q u,表示询问以u为根的子树中的总果子数,注意包括u本身的。(0≤u≤N-1)
1≤N≤100000,1≤Q≤100000
Output
输出询问的答案。
Sample Input
4
0 1
1 2
2 3
4
A 1 3 1
Q 0
Q 1
Q 2
Sample Output
3
3
2

//记下dfs序,就知道子树的范围了
//对一段范围进行加值,lazy操作
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
#include <vector>
using namespace std; typedef long long ll;
const int N=100001; int e[N*2],nxt[N*2],head[N];
int dep[N],fa[N],siz[N],w[N],top[N],son[N],End[N]; struct A{
ll sum,tag;
}t[N*4]; int n,C=0,edge=0;
void add(int x,int y)
{
e[++edge]=y;
nxt[edge]=head[x];
head[x]=edge;
} void dfs1(int x,int f,int d)
{//求size,dep,son,fa
dep[x]=d;fa[x]=f;siz[x]=1;
int i,tp=0;
for(i=head[x];i;i=nxt[i])
if(e[i]!=fa[x])
{
dfs1(e[i],x,d+1);
siz[x]+=siz[e[i]];
if(siz[e[i]]>tp){tp=siz[e[i]];son[x]=e[i];}
}
} void dfs2(int x,int tp)
{//求dfs序,链的顶端节点
w[x]=++C;
top[x]=tp;
if(son[x])
dfs2(son[x],top[x]);
for(int i=head[x];i;i=nxt[i])
if(e[i]!=son[x]&&e[i]!=fa[x])
dfs2(e[i],e[i]);
End[x]=C;//x所在子树的最大dfs序
} void build(int x,int l,int r)
{//建立线段树
t[x].tag=t[x].sum=0;
if(l==r) return;
int M=l+r>>1;
build(x<<1,l,M);
build(x<<1|1,M+1,r);
} void pushdown(int x,int l,int r)
{//在线段树中下传标记
if(t[x].tag)
{
t[x<<1].tag+=t[x].tag;
t[x<<1|1].tag+=t[x].tag;
int M=l+r>>1;
t[x<<1].sum+=(M-l+1)*t[x].tag;
t[x<<1|1].sum+=(r-M)*t[x].tag;
t[x].tag=0;
}
} void update(int x,int l,int r,int ql,int qr,int v)
{//在线段树中更新[ql,qr]节点权值加v
if(ql<=l&&qr>=r)
{
t[x].sum+=(r-l+1)*v;
t[x].tag+=v;
return;
}
pushdown(x,l,r);
int M=l+r>>1;
if(ql<=M)
update(x<<1,l,M,ql,qr,v);
if(qr>M)
update(x<<1|1,M+1,r,ql,qr,v);
t[x].sum=t[x<<1].sum+t[x<<1|1].sum;
} ll query(int x,int l,int r,int ql,int qr)
{//在线段树中查询[ql,qr]的权值和
if(ql<=l&&qr>=r) return t[x].sum;
pushdown(x,l,r);
int M=l+r>>1;ll sum=0;
if(ql<=M) sum+=query(x<<1,l,M,ql,qr);
if(qr>M) sum+=query(x<<1|1,M+1,r,ql,qr);
return sum;
} void upd(int x,int y,int z)
{//修改操作,见课件
int f1=top[x],f2=top[y],tmp;
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
tmp=f1;f1=f2;f2=tmp;
tmp=x;x=y;y=tmp;
}
update(1,1,n,w[f1],w[x],z);
x=fa[f1];
f1=top[x];
}
if(dep[x]<dep[y]){tmp=x;x=y;y=tmp;}
update(1,1,n,w[y],w[x],z); //注意这一句,本题是对点权进行操作
} int main()
{
int i,x,y,m,z;char c;
scanf("%d",&n);
for(i=1;i<n;i++)
{
scanf("%d %d",&x,&y);x++;y++;
add(x,y);
add(y,x);
}
dfs1(1,-1,1);
dfs2(1,1);
build(1,1,n);
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("\n%c",&c);
if(c=='A')
{
scanf("%d %d %d",&x,&y,&z);x++;y++;
upd(x,y,z);
}
else
{
scanf("%d",&x);//统计以x为根的子树的权值
x++;
printf("%lld\n",query(1,1,n,w[x],End[x]));
}
}
return 0;
}

  

shoi 魔法树的更多相关文章

  1. noip模拟赛(一)魔法树

    魔法树 (mahou.pas/c/cpp) [问题描述] 魔法使moreD在研究一棵魔法树. 魔法树顾名思义,这货是一棵树,奇葩的是魔法树上的每一条边都拥有一个魔法属性,如果不那么奇葩就不是moreD ...

  2. [SHOI 2012] 魔法树

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2836 [算法] 树链剖分 时间复杂度 : O(NlogN ^ 2) [代码] #in ...

  3. 洛谷 3833 SHOI 2012 魔法树

    [题解] 树链剖分模板题.. #include<cstdio> #include<algorithm> #include<queue> #define N 5000 ...

  4. [bzoj2836] 魔法树

    俩操作:增加路径上的点的权值.查询子树的权值和. 想了想似乎只能树链剖分了..好久没写链剖+数据结构了TAT 一开始没开LL炸了一发(明明有想到的..我果然是傻逼= = #include<cst ...

  5. P3833 [SHOI2012]魔法树

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

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

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

  7. 【树链剖分】【dfs序】【线段树】bzoj2836 魔法树

    这道题告诉我们:树链剖分的重标号就是dfs序. #include<cstdio> #include<algorithm> using namespace std; #defin ...

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

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

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

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

随机推荐

  1. 单调队列优化DP || [NOI2005]瑰丽华尔兹 || BZOJ 1499 || Luogu P2254

    题外话:题目极好,做题体验极差 题面:[NOI2005]瑰丽华尔兹 题解: F[t][i][j]表示第t时刻钢琴位于(i,j)时的最大路程F[t][i][j]=max(F[t-1][i][j],F[t ...

  2. creat-react-app生成的项目默认端口号是3000,如何更改?

    从项目的 package.json 文件中可以看到,npm start即scripts start.js,因此我们找到scripts/start.js ,部分代码如下: 找到 DEFAULT_PORT ...

  3. [易学易懂系列|rustlang语言|零基础|快速入门|(7)|函数Functions与闭包Closure]

    [易学易懂系列|rustlang语言|零基础|快速入门|(7)函数Functions与闭包Closure] 有意思的基础知识 函数Functions与闭包Closure 我们今天再来看看函数. 在Ru ...

  4. 「LCT」

    终于在多篇题解和我的个人超常发挥下抄完了lct的所有题,kx死了. 理解 在我看来,实际上lct的板子没有什么考的,更重要的可能是起到一个数据结构的维护作用实际上就是出题人想给你找点乐子. 前几道题都 ...

  5. docker python3环境搭建

    1.使用镜像为daocloud的python镜像 docker run -it --rm --name my-running-script -v "$PWD":/usr/src/m ...

  6. postman-变量

    Variables 什么是变量 变量是一个符号,可以接受不同的值.你可能根据你的项目经验,对其他语言的变量比较熟悉.在postman 的工作原理也是一样的 为什么使用变量 变量允许你在不同的地方重复使 ...

  7. jQuery字体图标的三种方法

    BootStrap框架原生图标 在导入BootStrap包的同时,导入bootstrap-3.3.7-dist/css/bootstrap.css层叠样式; <button type=" ...

  8. TCP,UDP,HTTP

    使用图表非常系统介绍了TCP和UDP的区别 https://blog.fundebug.com/2019/03/22/differences-of-tcp-and-udp/ 举了一个TCP/IP通讯的 ...

  9. 关于SQL注入的问题以及解决方法

    1.关于SQL注入 什么是SQL注入: 由于jdbc程序在执行的过程中sql语句在拼装时使用了由页面传入参数,如果用户恶意传入一些sql中的特殊关键字,会导致sql语句意义发生变化,这种攻击方式就叫做 ...

  10. 第五周课程总结&试验报告 (三)

    课程总结 一,类的继承格式 1.在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下: class 父类 {} class 子类 extends 父类 {} ...