Description

别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求你在这棵树上维护两种事件

事件0:

这棵树长出了一些果子, 即某个子树中的每个节点都会长出K个果子.

事件1:

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

Input

第一行一个整数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的结果.

Output

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

Sample Input

5

1 2

2 3

2 4

1 5

3

0 1 1

0 2 3

1 2 3 1 1 4

Sample Output

13

HINT

1 <= n <= 200,000, 1 <= nQ <= 200,000, K = 5.

生成每个树枝的过程是这样的:先在树中随机找一个节点, 然后在这个节点到根的路径上随机选一个节点, 这两个节点就作为树枝的两端.

Sol

这题为啥要容斥啊,不就一线段树+树剖题吗。(不过BIT的log*32确实比树剖的俩log*5快)

我们在线段树中维护当前的总和sum以及实际有效的值val,每次查询的时候,把树链上面的点系数改成1,之后获得答案,然后再把整棵树的系数改成0。

写完之后居然没调就过了样例???(逃

Code

#include <bits/stdc++.h>
#define mid ((s[x].l+s[x].r)>>1)
using namespace std;
struct seg{int l,r,sum,val,tag,lzy;}s[2000005];
int n,x,y,op,m,z,I,fa[400005],dep[400005],top[400005],son[400005],siz[400005],id[400005];
vector<int>e[400005];
int dfs1(int x)
{
int maxx=0,tot=0;
for(int i=0;i<e[x].size();i++) if(e[x][i]!=fa[x])
{
dep[e[x][i]]=dep[x]+1;fa[e[x][i]]=x;tot+=dfs1(e[x][i]);
if(siz[e[x][i]]>maxx) maxx=siz[e[x][i]],son[x]=e[x][i];
}
return siz[x]=tot+1;
}
void dfs2(int x,int Fa)
{
id[x]=++I;top[x]=Fa;
if(son[x]) dfs2(son[x],Fa);
for(int i=0;i<e[x].size();i++) if(e[x][i]!=fa[x]&&e[x][i]!=son[x]) dfs2(e[x][i],e[x][i]);
}
void build(int x,int L,int R)
{
s[x]=(seg){L,R,0,0,-1,0};
if(L==R) return;
build(x*2,L,mid);build(x*2+1,mid+1,R);
}
void down(int x)
{
s[x*2].sum+=s[x].lzy*(s[x*2].r-s[x*2].l+1);s[x*2+1].sum+=s[x].lzy*(s[x*2+1].r-s[x*2+1].l+1);
s[x*2].lzy+=s[x].lzy;s[x*2+1].lzy+=s[x].lzy;s[x].lzy=0;
if(s[x].tag==-1) return;
s[x*2].val=s[x].tag*s[x*2].sum;s[x*2+1].val=s[x].tag*s[x*2+1].sum;
s[x*2].tag=s[x*2+1].tag=s[x].tag;s[x].tag=-1;
}
void update(int x,int L,int R,int V,int O)
{
down(x);
if(L<=s[x].l&&s[x].r<=R)
{
if(!O) s[x].val=s[x].sum*V,s[x].tag=V;
else s[x].lzy+=V,s[x].sum+=V*(s[x].r-s[x].l+1);
return;
}
if(L<=mid) update(x*2,L,R,V,O);if(R>mid) update(x*2+1,L,R,V,O);
s[x].sum=s[x*2].sum+s[x*2+1].sum;s[x].val=s[x*2].val+s[x*2+1].val;
}
void solve(int x,int y)
{
for(;top[x]!=top[y];update(1,id[top[x]],id[x],1,0),x=fa[top[x]]) if(dep[top[x]]<dep[top[y]]) swap(x,y);
if(dep[x]>dep[y]) swap(x,y);update(1,id[x],id[y],1,0);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++) scanf("%d%d",&x,&y),e[x].push_back(y),e[y].push_back(x);
dfs1(1);dfs2(1,1);build(1,1,n);
for(scanf("%d",&m);m--;)
{
scanf("%d",&op);
if(!op){scanf("%d%d",&x,&y),update(1,id[x],id[x]+siz[x]-1,y,1);continue;}
for(scanf("%d",&z);z--;) scanf("%d%d",&x,&y),solve(x,y);
printf("%d\n",s[1].val&0x7fffffff);update(1,1,n,0,0);
}
}

【BZOJ3589】动态树 树链剖分+线段树的更多相关文章

  1. 【bzoj5210】最大连通子块和 树链剖分+线段树+可删除堆维护树形动态dp

    题目描述 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块和. 其中,一棵子树的最大连通子块和指的是:该子树 ...

  2. 【bzoj4712】洪水 树链剖分+线段树维护树形动态dp

    题目描述 给出一棵树,点有点权.多次增加某个点的点权,并在某一棵子树中询问:选出若干个节点,使得每个叶子节点到根节点的路径上至少有一个节点被选择,求选出的点的点权和的最小值. 输入 输入文件第一行包含 ...

  3. 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点

    题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...

  4. BZOJ 3589 动态树 (树链剖分+线段树)

    前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...

  5. B20J_3231_[SDOI2014]旅行_树链剖分+线段树

    B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...

  6. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  7. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  8. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  9. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  10. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

随机推荐

  1. java成神之——Stream和Optional

    Stream流 基本使用 流关闭 平行流 流重用 iterator转换成流 分组计数 无限流 流转集合 压缩流 统计数值流 集合转换流遍历 流拼接 reduce 使用流生成随机字符串 流的包装流 几种 ...

  2. pandas分组和聚合

    Pandas分组与聚合 分组 (groupby) 对数据集进行分组,然后对每组进行统计分析 SQL能够对数据进行过滤,分组聚合 pandas能利用groupby进行更加复杂的分组运算 分组运算过程:s ...

  3. 点击jQuery Mobile的按钮改变颜色

    jquery-mobile-移动 我有这样的代码来改变点击一个按钮的颜色: $('.fav').live('click', function(e) { $(this).buttonMarkup({ t ...

  4. javascript中的装箱和拆箱操作

    1,装箱: 把基本数据类型转换为对应的引用类型的操作称为装箱,把引用类型转换为基本的数据类型称为拆箱. 在<javascript高级程序设计>中有这样一句话: 每当读取一个基本类型的时候, ...

  5. 每天一个Linux命令 - 【groupadd】

    [命令]:grouadd [语法]:groupadd [选项]   [参数] [功能介绍]:groupadd 命令勇于创建新的工作组,新工作组的信息将被添加的系统文件中. [选项说明]: -g < ...

  6. wordpress 学习笔记

    (1) __()函数 function __( $text, $domain = 'default' ) { return translate( $text, $domain ); } 返回一个字符串 ...

  7. [故障及解决]SoundPool没有声音

    问题描述:使用SoundPool类进行播放声音时,在手机上没有声音. 问题代码: /** * 声音播放 */ private void playSound() { SoundPool soundPoo ...

  8. Spark的几个问题

    1.application是由driver和executor组成的,executor可以分成task,task又可以分成为stage.当一个任务提交给spark之后,spark机群的主节点会出现dri ...

  9. Spring Data系列之Jpa(一)

    1.Spring Data的由来 Spring Data是SpringSource基金会创下的一个简化数据库访问.支持云服务的开源框架.其主要目的是让数据库访问变的方便快捷,可以用Spring Dat ...

  10. Leetcode:Regular Expression Matching分析和实现

    题目大意是要求我们实现一个简单的正则表达式全匹配判断.其中正则表达式中只包含一般字符,以及全匹配字符.和变长字符*.其中.可以匹配一个字符,而*与前一个字符相关联,x*可以被看作任意多个x(0到正无穷 ...