【BZOJ3589】动态树 树链剖分+线段树
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】动态树 树链剖分+线段树的更多相关文章
- 【bzoj5210】最大连通子块和 树链剖分+线段树+可删除堆维护树形动态dp
题目描述 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块和. 其中,一棵子树的最大连通子块和指的是:该子树 ...
- 【bzoj4712】洪水 树链剖分+线段树维护树形动态dp
题目描述 给出一棵树,点有点权.多次增加某个点的点权,并在某一棵子树中询问:选出若干个节点,使得每个叶子节点到根节点的路径上至少有一个节点被选择,求选出的点的点权和的最小值. 输入 输入文件第一行包含 ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- BZOJ 3589 动态树 (树链剖分+线段树)
前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...
- B20J_3231_[SDOI2014]旅行_树链剖分+线段树
B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
随机推荐
- vc6.0出现“cannot add new member”解决办法
在编辑一个工程的时候,添加一个按钮,对这个按钮产生消息函数 双击按钮之后出现 cannot add new member 网上说删除.clw文件 我发现并没有这个后缀的文件 以下是我的操作办法: ...
- js取得前2位字符
<label id="ab">0</label> <script language="javascript"> url=&q ...
- CentOS7上elasticsearch5.5启动报错
ERROR: [2] bootstrap checks failed [1]: max file descriptors [4096] for elasticsearch process is too ...
- Django界面不能添加中文解决办法
Django项目部署好后,界面添加中文会报错,解决办法: 创建数据库时要指定编码格式: CREATE DATABASE blog CHARACTER SET utf8; 如果已经创建完毕则修改: al ...
- c++builder PM2.5
c++builder PM2.5 TMemoryStream *ms = new TMemoryStream(); this->NetHTTPClient1->Get("http ...
- React 常用面试题目与分析
调用 setState 之后发生了什么? 在代码中调用setState函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation).经过调和过程 ...
- bash shell笔记4 处理用…
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/521448 知 ...
- ubuntu网速慢解决方法
ubuntu网速慢解决方法 (2011-04-02 09:58:21) 本人在Window7下装ubuntu10.10双系统,在window7下速度挺快的,到了ubuntu速度就慢了很 ...
- imp导入数据的时候报错:ORA-01658: 无法为表空间 MAXDATA 中的段创建 INITIAL 区
在oracle里创建表,报出错: ORA-01658: 无法为表空间space中的段创建 INITIAL 区: 或者: ORA-01658: unable to create INITIAL exte ...
- javascript实现新浪微博MID与地址转换
新浪微博每一条微博都会有一个mid,然后每条微博都有一个独立的地址,例如:http://www.weibo.com//Bw3SXzWzP 规律:地址中的黄色部分是用户id,绿色部分是微博的识别字符串, ...