题目描述

别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求你在这棵树上维护两种事件
事件0:
这棵树长出了一些果子, 即某个子树中的每个节点都会长出K个果子.
事件1:

小明希望你求出几条树枝上的果子数. 一条树枝其实就是一个从某个节点到根的路径的一段. 每次小明会选定一些树枝, 让你求出在这些树枝上的节点的果子数的和. 注意, 树枝之间可能会重合, 这时重合的部分的节点的果子只要算一次.

输入

第一行一个整数n(1<=n<=200,000), 即节点数.
接下来n-1行, 每行两个数字u, v. 表示果子u和果子v之间有一条直接的边. 节点从1开始编号.
在接下来一个整数nQ(1<=nQ<=200,000), 表示事件.
最后nQ行, 每行开头要么是0, 要么是1.
如果是0, 表示这个事件是事件0. 这行接下来的2个整数u, delta表示以u为根的子树中的每个节点长出了delta个果子.

如果是1, 表示这个事件是事件1. 这行接下来一个整数K(1<=K<=5), 表示这次询问涉及K个树枝. 接下来K对整数u_k, v_k, 每个树枝从节点u_k到节点v_k. 由于果子数可能非常多, 请输出这个数模2^31的结果.

输出

对于每个事件1, 输出询问的果子数.

样例输入

5
1 2
2 3
2 4
1 5
3
0 1 1
0 2 3
1 2 3 1 1 4

样例输出

13
解析
因为是动态的,所以放弃倍增LCA,考虑树链剖分(为什么做树的问题时我脑子里只有这两个东西?)。
对于事件0,直接在dfs序上区间修改x及其子树,即从x到x+siz[x]-1全部加k。
对于事件1,先对于每条链,求出它在dfs序上对应的区间,然后将这些区间合并起来,最后查询即可
合并区间的时候,先按照左端点由小到大给区间排序,然后从小到大遍历,若当前区间的右端点在下一个区间左端点的右边就可以把两个区间合并起来。
还有就是模2^31的问题,找Master Yi问了一下,好像是可以不管炸int的,只需要在最后&一下2^31-1即可。
代码如下
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=;
const int inf=;
struct node{int l,r;}q[maxn];
int en,mk[maxn<<],sum[maxn<<];
int n,Q,id,info[maxn],nx[maxn<<],v[maxn<<];
int fa[maxn],dep[maxn],dfn[maxn],siz[maxn],son[maxn],top[maxn];
bool cmp(node a,node b){return a.l==b.l?a.r<b.r:a.l<b.l;}
void add(int u1,int v1){nx[++id]=info[u1];info[u1]=id;v[id]=v1;}
void dfs1(int x,int f)
{
dep[x]=dep[fa[x]=f]+(siz[x]=);
for(int i=info[x];i;i=nx[i])if(v[i]!=f)
{
dfs1(v[i],x);siz[x]+=siz[v[i]];
if(siz[v[i]]>siz[son[x]])son[x]=v[i];
}
}
void dfs2(int x,int f)
{
dfn[x]=++id;top[x]=f;if(son[x])dfs2(son[x],f);
for(int i=info[x];i;i=nx[i])if(v[i]!=fa[x]&&v[i]!=son[x])dfs2(v[i],v[i]);
}
void pushdown(int id,int l,int r)
{
int mid=(l+r)/;
mk[id*]+=mk[id];mk[id*+]+=mk[id];
sum[id*]+=(mid-l+)*mk[id];sum[id*+]+=(r-mid)*mk[id];mk[id]=;
}
void fix(int id,int l,int r,int l1,int r1,int k)
{
if(r1<l||r<l1)return;
if(l1<=l&&r<=r1){sum[id]+=k*(r-l+);mk[id]+=k;return;}
pushdown(id,l,r);int mid=(l+r)/;
fix(id*,l,mid,l1,r1,k);fix(id*+,mid+,r,l1,r1,k);sum[id]=sum[id*]+sum[id*+];
}
int que(int id,int l,int r,int l1,int r1)
{
if(r1<l||r<l1)return ;
if(l1<=l&&r<=r1)return sum[id];
pushdown(id,l,r);int mid=(l+r)/;
return que(id*,l,mid,l1,r1)+que(id*+,mid+,r,l1,r1);
}
int main()
{
scanf("%d",&n);
for(int i=,u1,v1;i<n;i++)scanf("%d%d",&u1,&v1),add(u1,v1),add(v1,u1);
id=;dfs1(,);dfs2(,);id=;
scanf("%d",&Q);
for(int i=,ord,x,k;i<=Q;i++)
{
scanf("%d",&ord);
if(ord==)scanf("%d%d",&x,&k),fix(,,n,dfn[x],dfn[x]+siz[x]-,k);
if(ord==)
{
scanf("%d",&k);en=;
for(int i=,a,b;i<=k;i++)
{
scanf("%d%d",&a,&b);
if(dep[b]>dep[a])swap(a,b);
while(top[a]!=top[b])q[++en]=(node){dfn[top[a]],dfn[a]},a=fa[top[a]];
q[++en]=(node){dfn[b],dfn[a]};
}
sort(q+,q++en,cmp);
int ans=;
for(int i=,l,r;i<=en;i++)
{
l=q[i].l,r=q[i].r;
while(q[i+].l<=r&&i+<=en)r=max(q[i+].r,r),i++;
ans+=que(,,n,l,r);
}
printf("%d\n",ans&inf);
}
}
}

 

[树链剖分]BZOJ3589动态树的更多相关文章

  1. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5020  Solved: 1872[Submit][Status ...

  2. bzoj 4034 [HAOI2015] T2(树链剖分,线段树)

    4034: [HAOI2015]T2 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1536  Solved: 508[Submit][Status] ...

  3. bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit ...

  4. poj 3237 Tree(树链剖分,线段树)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7268   Accepted: 1969 Description ...

  5. bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1272  Solved: 451[Submit][Status ...

  6. bzoj 2243 [SDOI2011]染色(树链剖分,线段树)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4637  Solved: 1726[Submit][Status ...

  7. HDU 4366 Successor(树链剖分+zkw线段树+扫描线)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4366 [题目大意] 有一个公司,每个员工都有一个上司,所有的人呈树状关系,现在给出每个人的忠诚值和 ...

  8. 【BZOJ3531】旅行(树链剖分,线段树)

    [BZOJ3531]旅行(树链剖分,线段树) 题面 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教 ...

  9. 【BZOJ5507】[GXOI/GZOI2019]旧词(树链剖分,线段树)

    [BZOJ5507][GXOI/GZOI2019]旧词(树链剖分,线段树) 题面 BZOJ 洛谷 题解 如果\(k=1\)就是链并裸题了... 其实\(k>1\)发现还是可以用类似链并的思想,这 ...

随机推荐

  1. 易百教程人工智能python修正-人工智能数据准备-标记数据

    我们已经知道,某种格式的数据对于机器学习算法是必需的. 另一个重要的要求是,在将数据作为机器学习算法的输入发送之前,必须正确标记数据. 例如,如果所说的分类,那么数据上会有很多标记. 这些标记以文字, ...

  2. 能够提高PHP的性能的一些注意事项

      1. 如果能将类的方法定义成static,就尽量定义成static,它的速度会提升将近4倍.(静态类调用属性和方法,只可以调用静态属性和方法.self::方法名().self::属性名.只有实例化 ...

  3. csrf 功能 及 csrf装饰器使用

    目录 csrf 功能 及 csrf装饰器使用 简单了解csrf 防范措施 了解更多csrf点击 django 中 csrf csrf装饰器 csrf功能(执行流程) csrf 功能 及 csrf装饰器 ...

  4. webpack--splitChunksPlugin配置学习随笔

    该配置用于代码抽离.官方文档 官方默认配置: module.exports = { //... optimization: { splitChunks: { chunks: 'async', // 异 ...

  5. Referenced file contains errors (xml文件第一行小红叉错误)

    转自:http://www.manongjc.com/article/30401.html 在eclipse中开发网页时,经常会遇到写xml文件时第一行无缘无故报错.在最左面的行数上面报出一个小红叉, ...

  6. python面试总结4(算法与内置数据结构)

    算法与内置数据结构 常用算法和数据结构 sorted dict/list/set/tuple 分析时间/空间复杂度 实现常见数据结构和算法 数据结构/算法 语言内置 内置库 线性结构 list(列表) ...

  7. containerd简述

    containerd是容器虚拟化技术,从docker中剥离出来,形成开放容器接口(OCI)标准的一部分. docker对容器的管理和操作基本都是通过containerd完成的.Containerd 是 ...

  8. Flink原理(五)——容错机制

    本文是博主阅读Flink官方文档以及<Flink基础教程>后结合自己理解所写,若有表达有误的地方欢迎大伙留言指出. 1.  前言 流式计算分为有状态和无状态两种情况,所谓状态就是计算过程中 ...

  9. React系列,初识

    学习react对于新手来说,还没有学react往往就会被webpack,npm等搞的晕头转向,所以我们今天就从最简单的方式入手 <script src="react.js"& ...

  10. mysql 杂记 —— 时区问题

    查看时区: SHOW VARIABLES LIKE "%time_zone%"; 输出 Variable_name Value system_time_zone CST time_ ...