[树链剖分]BZOJ3589动态树
题目描述
小明希望你求出几条树枝上的果子数. 一条树枝其实就是一个从某个节点到根的路径的一段. 每次小明会选定一些树枝, 让你求出在这些树枝上的节点的果子数的和. 注意, 树枝之间可能会重合, 这时重合的部分的节点的果子只要算一次.
输入
如果是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动态树的更多相关文章
- Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5020 Solved: 1872[Submit][Status ...
- bzoj 4034 [HAOI2015] T2(树链剖分,线段树)
4034: [HAOI2015]T2 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1536 Solved: 508[Submit][Status] ...
- bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 10677 Solved: 4313[Submit ...
- poj 3237 Tree(树链剖分,线段树)
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 7268 Accepted: 1969 Description ...
- bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1272 Solved: 451[Submit][Status ...
- bzoj 2243 [SDOI2011]染色(树链剖分,线段树)
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4637 Solved: 1726[Submit][Status ...
- HDU 4366 Successor(树链剖分+zkw线段树+扫描线)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4366 [题目大意] 有一个公司,每个员工都有一个上司,所有的人呈树状关系,现在给出每个人的忠诚值和 ...
- 【BZOJ3531】旅行(树链剖分,线段树)
[BZOJ3531]旅行(树链剖分,线段树) 题面 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教 ...
- 【BZOJ5507】[GXOI/GZOI2019]旧词(树链剖分,线段树)
[BZOJ5507][GXOI/GZOI2019]旧词(树链剖分,线段树) 题面 BZOJ 洛谷 题解 如果\(k=1\)就是链并裸题了... 其实\(k>1\)发现还是可以用类似链并的思想,这 ...
随机推荐
- TCP_Wrappers基础知识介绍
1. TCP_Wrappers基础知识介绍 TCP_Wrappers是在 Solaris, HP_UX以及 Linux中广泛流行的免费软件.它被设计为一个介于外来服务请求和系统服务回应的中间处理软件. ...
- 0001-代码仓库-mvn
暂缺 基本介绍 web管理 ifsvnadmin
- python获取第前多少天的日期
1. 显示昨天(前一天)的日期 from datetime import date, timedelta yesterday_date = (date.today() + timedelta(days ...
- C实现栈与队列
C实现栈与队列 做了个栈和队列的基础demo,写得比较快,就没有什么注释,其实看各个函数的名字就可以知道函数的作用了. 栈的实现 #include <stdio.h> #include & ...
- 高并发架构系列:Redis并发竞争key的解决方案详解
https://blog.csdn.net/ChenRui_yz/article/details/85096418 https://blog.csdn.net/ChenRui_yz/article/l ...
- wireshark 抓包再利用TCP socket发送包里的payload是可以实现登陆的
用户密码可被批量破解 在用户使用手机端登录时,对数据进行抓包分析. 多次抓包分析后,可得到几个关键TCP数据包. 根据前面逆向编写出的解密算法,使用socket进行数据发包测试: 可以模拟APK进行用 ...
- jdk1.8换成11,启动项目报错java.net.MalformedURLException: unknown protocol: jrt
jdk11 Information:Internal caches are corrupted or have outdated format, forcing project rebuild: Mo ...
- python get/post接口使用
背景: 使用python调用get post接口,入参.出参都需要转换,在使用时经常会忘记其中的一步,本文用来记录,后面再使用时直接参考使用 代码如下 post: headers = {'Conten ...
- PHP——封装Curl请求方法支持POST | DELETE | GET | PUT 等
前言 Curl: https://www.php.net/manual/en/book.curl.php curl_setopt: https://www.php.net/manual/en/fun ...
- c语言中,如果将无符号数转换为有符号数
在使用ti的adc芯片ads1259时,芯片是24为数据格式保存的,其中最高位是符号位,因此可以理解为是有符号数据,但是在嵌入式系统中,没有直接24位的变量,因此使用32的无符号先保存24位的数据. ...