树链剖分【洛谷P3833】 [SHOI2012]魔法树
P3833 [SHOI2012]魔法树
题目描述
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 ≤ Q ≤ 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 。
省选考树剖裸题。。。
code:
#include <iostream>
#include <cstdio>
#define ls(o) o<<1
#define rs(o) o<<1|1
#define int long long
using namespace std;
const int wx=100017;
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
return sum*f;
}
int dfn[wx],tid[wx];
int dep[wx],f[wx],size[wx],son[wx];
int top[wx];
int head[wx],a[wx];
int n,m,num,tot;
char opt[17];
struct val_tree{
int l,r,tag,sum;
#define tag(o) t[o].tag
#define sum(o) t[o].sum
}t[wx*4];
void up(int o){
sum(o)=sum(ls(o))+sum(rs(o));
}
void down(int o){
if(tag(o)){
sum(ls(o))+=tag(o)*(t[ls(o)].r-t[ls(o)].l+1);
sum(rs(o))+=tag(o)*(t[rs(o)].r-t[rs(o)].l+1);
tag(ls(o))+=tag(o); tag(rs(o))+=tag(o);
tag(o)=0;
}
}
void build(int o,int l,int r){
t[o].l=l;t[o].r=r;
if(l==r){sum(o)=a[tid[l]];return ;}
int mid=t[o].l+t[o].r>>1;
if(l<=mid)build(ls(o),l,mid);
if(r>mid)build(rs(o),mid+1,r);
up(o);
}
void update_t(int o,int l,int r,int k){
if(l<=t[o].l&&t[o].r<=r){
sum(o)+=k*(t[o].r-t[o].l+1);
tag(o)+=k; return ;
}
down(o);
int mid=t[o].l+t[o].r>>1;
if(l<=mid)update_t(ls(o),l,r,k);
if(r>mid)update_t(rs(o),l,r,k);
up(o);
}
int query_t(int o,int l,int r){
if(l<=t[o].l&&t[o].r<=r){
return sum(o);
}
down(o); int sum=0;
int mid=t[o].l+t[o].r>>1;
if(l<=mid)sum+=query_t(ls(o),l,r);
if(r>mid)sum+=query_t(rs(o),l,r);
return sum;
}
//~~~~~~~~~~~~~~~~~~~~~~~~
struct e{
int nxt,to;
}edge[wx*2];
void add(int from,int to){
edge[++num].nxt=head[from];
edge[num].to=to;
head[from]=num;
}
void first_dfs(int u,int fa){
f[u]=fa;dep[u]=dep[fa]+1;
size[u]=1;
int maxson=-1;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa)continue;
first_dfs(v,u);
size[u]+=size[v];
if(size[v]>maxson){
son[u]=v; maxson=size[v];
}
}
}
void second_dfs(int u,int topf){
dfn[u]=++tot;
top[u]=topf;
tid[tot]=u;
if(son[u]){
second_dfs(son[u],topf);
}
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(dfn[v]||v==son[u])continue;
second_dfs(v,v);
}
}
void update(int x,int y,int k){
int fx=top[x]; int fy=top[y];
while(fx!=fy){
if(dep[fx]>dep[fy]){
update_t(1,dfn[fx],dfn[x],k);
x=f[fx];
}
else{
update_t(1,dfn[fy],dfn[y],k);
y=f[fy];
}
fx=top[x]; fy=top[y];
}
if(dfn[x]>dfn[y]) swap(x,y);
update_t(1,dfn[x],dfn[y],k);
return ;
}
signed main(){
n=read();
for(int i=1;i<n;i++){
int x,y;
x=read(); y=read();
x++; y++;
add(x,y);add(y,x);
}
first_dfs(1,0);
second_dfs(1,1);
build(1,1,n);
m=read();
for(int i=1;i<=m;i++){
scanf("%s",opt+1);
if(opt[1]=='A'){
int x,y,z;
x=read();y=read();z=read();
x++; y++;
update(x,y,z);
}
else{
int x; x=read(); x++;
printf("%lld\n",query_t(1,dfn[x],dfn[x]+size[x]-1));
}
}
return 0;
}
树链剖分【洛谷P3833】 [SHOI2012]魔法树的更多相关文章
- 洛谷——P3833 [SHOI2012]魔法树
P3833 [SHOI2012]魔法树 题目背景 SHOI2012 D2T3 题目描述 Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的 ...
- 洛谷 P3833 [SHOI2012]魔法树
题目背景 SHOI2012 D2T3 题目描述 Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的新法术. 这棵果树共有N个节点,其中节点 ...
- [洛谷P3833][SHOI2012]魔法树
题目大意:给一棵树,路径加,子树求和 题解:树剖 卡点:无 C++ Code: #include <cstdio> #include <iostream> #define ma ...
- 洛谷3833 [SHOI2012]魔法树
SHOI2012 D2T3 题目描述 Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的新法术. 这棵果树共有N个节点,其中节点0是根节点 ...
- AC日记——【模板】树链剖分 洛谷 P3384
题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...
- 洛谷P3833 [SHOI2012]魔法树(树链剖分)
传送门 树剖板子…… 一个路径加和,线段树上打标记.一个子树询问,dfs的时候记录一下子树的区间就行 // luogu-judger-enable-o2 //minamoto #include< ...
- P3833 [SHOI2012]魔法树
思路 树剖板子 注意给出点的编号是从零开始的 代码 #include <cstdio> #include <algorithm> #include <cstring> ...
- 洛谷 P3384 【模板】树链剖分
树链剖分 将一棵树的每个节点到它所有子节点中子树和(所包含的点的个数)最大的那个子节点的这条边标记为"重边". 将其他的边标记为"轻边". 若果一个非根节点的子 ...
- 树链剖分详解(洛谷模板 P3384)
洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...
- ⌈洛谷1505⌋⌈BZOJ2157⌋⌈国家集训队⌋旅游【树链剖分】
题目链接 [洛谷] [BZOJ] 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T ...
随机推荐
- maven学习7 settings.xml解析
maven的配置文件settings.xml存在于两个地方: 1.安装的地方:${M2_HOME}/conf/settings.xml 2.用户的目录:${user.home}/.m2/setting ...
- mybatis如何防止sql注入(1)
sql注入大家都不陌生,是一种常见的攻击方式,攻击者在界面的表单信息或url上输入一些奇怪的sql片段,例如“or ‘1’=‘1’”这样的语句,有可能入侵参数校验不足的应用程序.所以在我们的应用中需要 ...
- [转]浅谈javascript函数劫持
转自:Ph4nt0m Security Team 这么多年了,现在学习依然还是有很多收货,向前辈致敬.转载一方面是自己存档一份,另一方面是让更多喜欢安全的人一同学习. ================ ...
- Ettercap进行arp毒化
攻击者IP:192.168.220.152 受害者IP:192.168.220.151 网关:192.168.220.2 修改DNS文件 ┌─[root@sch01ar]─[~] └──╼ #vim ...
- c#的日志插件NLog基本使用
本文介绍c#的日志插件NLog 安装插件 创建logger 日志级别 书写日志信息 配置 包装器 布局 安装插件 直接下载插件包 Install-Package NLog.Config 创建logge ...
- Oracle中REGEXP_SUBSTR函数(字符串转多行)
Oracle中REGEXP_SUBSTR函数 Oracle中REGEXP_SUBSTR函数的使用说明: 题目如下: 在oracle中,使用一条语句实现将'17,20,23'拆分成'17','20',' ...
- BA 新web化 问题汇总
1. 3D堆栈图在winform端无法显示,但在web端可以正常显示,说明与浏览器版本有关,在 IE 中设置文档模式为 IE8 即报错,IE9 却正常显示,可在 <head>节点下添加如下 ...
- javascript——事件处理模型(DOM 和 IE)
javascript的事件处理模型分为 DOM事件处理模型和 IE事件处理模型. 一.DOM事件流模型 DOM事件流分为三个阶段:捕获阶段.目标阶段.冒泡阶段. 捕获阶段:自上而下,由document ...
- 2-2 zookeeper下载、安装以及配置环境变量
https://archive.apache.org/dist/zookeeper/zookeeper-3.4.11/ FTP的软件:FileZilla Client 登录腾讯云服务器tail /va ...
- 34- 24 Point game
http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=43 24 Point game 时间限制:3000 ms | 内存限制:65535 KB ...