题目:洛谷P3833。

题目大意:给你一棵树,有两种操作:1.给两个点和它们之间的最短路上的所有点加上一个值;2.询问以某个点为根的子树的子树和。你需要实现这个功能。

解题思路:如果只有最后才询问的话,本题可以用树上差分做。然而询问和修改是穿插的。

那么我们只能使用树链剖分了。

用树剖则很简单,修改就是边求lca边维护线段树。查询则是线段树区间查询。

由于本题从0开始编号,把每个点的编号+1,就变成从1开始编号(主要是因为习惯)。

时间复杂度$O(Q\log^2 n)$。

C++ Code:

#include<cstdio>
#include<cctype>
#include<cstring>
#define N 100005
#define ll long long
int n,head[N],cnt,sz[N],dep[N],son[N],top[N],fa[N],dfn[N],idx,t,L,R;
ll ans;
struct edge{
int to,nxt;
}e[N<<1];
struct SegmentTreeNode{
ll s,add;
}d[N<<2];
inline int readint(){
char c=getchar();
for(;!isdigit(c);c=getchar());
int d=0;
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
void dfs(int now){
sz[now]=1;
for(int i=head[now];i;i=e[i].nxt)
if(!dep[e[i].to]){
dep[e[i].to]=dep[now]+1;
fa[e[i].to]=now;
dfs(e[i].to);
sz[now]+=sz[e[i].to];
if(!son[now]||sz[son[now]]<sz[e[i].to])son[now]=e[i].to;
}
}
void dfs2(int now){
dfn[now]=++idx;
if(son[now])top[son[now]]=top[now],dfs2(son[now]);
for(int i=head[now];i;i=e[i].nxt)
if(e[i].to!=son[now]&&dep[now]<dep[e[i].to])
top[e[i].to]=e[i].to,dfs2(e[i].to);
}
inline void pushdown(int o,int len){
int ld=o<<1,rd=o<<1|1;
d[ld].add+=d[o].add;
d[ld].s+=d[o].add*((len+1)>>1);
d[rd].add+=d[o].add;
d[rd].s+=d[o].add*(len>>1);
d[o].add=0;
}
void addt(int l,int r,int o){
if(L<=l&&r<=R){
d[o].add+=t;
d[o].s+=(ll)t*(r-l+1);
}else{
pushdown(o,r-l+1);
int mid=(l+r)>>1;
if(L<=mid)addt(l,mid,o<<1);
if(mid<R)addt(mid+1,r,o<<1|1);
d[o].s=d[o<<1].s+d[o<<1|1].s;
}
}
void add(int x,int y){
for(;top[x]!=top[y];)
if(dep[top[x]]>=dep[top[y]]){
L=dfn[top[x]],R=dfn[x];
addt(1,n,1);
x=fa[top[x]];
}else{
L=dfn[top[y]],R=dfn[y];
addt(1,n,1);
y=fa[top[y]];
}
if(dep[x]<=dep[y])L=dfn[x],R=dfn[y];else
L=dfn[y],R=dfn[x];
addt(1,n,1);
}
void query(int l,int r,int o){
if(L<=l&&r<=R)ans+=d[o].s;else{
pushdown(o,r-l+1);
int mid=(l+r)>>1;
if(L<=mid)query(l,mid,o<<1);
if(mid<R)query(mid+1,r,o<<1|1);
}
}
int main(){
n=readint();
cnt=idx=0;
for(int i=1;i<n;++i){
int u=readint()+1,v=readint()+1;
e[++cnt]=(edge){v,head[u]};
head[u]=cnt;
e[++cnt]=(edge){u,head[v]};
head[v]=cnt;
}
dep[1]=top[1]=fa[1]=1;
dfs(1);dfs2(1);
memset(d,0,sizeof d);
for(int q=readint();q--;){
char c=getchar();
while(!isalpha(c))c=getchar();
if(c=='A'){
int x=readint()+1,y=readint()+1;t=readint();
add(x,y);
}else{
int u=readint()+1;
L=dfn[u],R=dfn[u]+sz[u]-1;
ans=0;
query(1,n,1);
printf("%lld\n",ans);
}
}
return 0;
}

[SHOI2012]魔法树的更多相关文章

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

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

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

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

  3. 洛谷3833 [SHOI2012]魔法树

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

  4. 洛谷 P3833 [SHOI2012]魔法树

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

  5. P3833 [SHOI2012]魔法树

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

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

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

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

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

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

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

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

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

随机推荐

  1. [LeetCode] 242. 有效的字母异位词 valid-anagram(排序)

    注意这里字母异位词的定义是:字母类别及个数都要一样,只是排列顺序不同. class Solution(object): def isAnagram(self, s, t): ""& ...

  2. js手动定时清除localStorage

    <script type="text/javascript"> // 假设要保存变量 a 的值,过期时间为 3600秒 // 保存值 var obj = new Obj ...

  3. tring.Format格式化用法

    (数字保留两位小数,且每隔3为用逗号隔开): string.format("1f,.2d",333) -->333.00 string.format("1f,.2d ...

  4. Windows里正确安装Zookeeper以服务运行

    不多说,直接上干货! 为什么要在Win下来安装Zookeeper呢? 其实玩过大数据的人很清楚,在Linux下我更不说了.在win下,如Disconf .Dubbo等应用. 所以,它的应用是非常广的. ...

  5. ASP.NET-POSTBACK是什么

    当我们直接从服务端读取网页时,表时此网页并没有post(提交),当用户再次提交表单时,就会把此网页的相关参数传给服务器处理,对于服务器来说就是一个postback(提交返回),即提交回来了.这就是po ...

  6. map和multimap映射容器

    map容器 map所处理的数据与数据库表具有键值的记录非常相似,在键值与映射数据之间,建立一个数学上的映射关系.map容器的数据结构仍然採用红黑树进行管理.插入的元素键值不同意反复,所使用的结点元素的 ...

  7. [Angular] Handle HTTP Errors in Angular with HttpErrorResponse interface

    When communicating with some backend API, data travels over the network using the HTTP protocol. As ...

  8. magento megatron主题加入中文

    magento的megatron默认不支持中文,全部我们须要在它的本地化目录中加入中文的cvs文件,加入方法例如以下: 1.切换至 app ▸ design ▸ frontend ▸ megatron ...

  9. 弹性ScrollView,和下啦刷新的效果相似 实现下拉弹回和上拉弹回

    今天做了一个弹性ScrollView,和下啦刷新的效果类似,我想这个非常多需求都用的这样的效果 事实上这是一个自己定义的scrollView,上代码.这是我写在一个公共的组件包里的 package c ...

  10. BZOJ 1101 莫比乌斯函数+分块

    思路: 题目中的gcd(x,y)=d (x<=a,y<=b)可以转化成 求:gcd(x,y)=1 (1<=x<=a/d 1<=y<=b/d) 设 G(x,y)表示x ...