BZOJ4372: 烁烁的游戏(动态点分治)
Description
背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠。
题意:
给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠。
烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠。皮皮鼠会被烁烁吸引,所以会一直待在节点上不动。
烁烁很好奇,在当前时刻,节点u有多少个他的好朋友---皮皮鼠。
大意:
给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:
Q x:询问x的点权。
M x d w:将树上与节点x距离不超过d的节点的点权均加上w。
Input
第一行两个正整数:n,m
接下来的n-1行,每行三个正整数u,v,代表u,v之间有一条边。
接下来的m行,每行给出上述两种操作中的一种。
Output
对于每个Q操作,输出当前x节点的皮皮鼠数量。
Sample Input
1 2
1 4
1 5
2 3
2 7
5 6
M 1 1 2
Q 5
M 2 2 3
Q 3
M 1 2 1
Q 2
Sample Output
3
6
解题思路:
和震波很像,查询修改反过来就好了。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
const int N=;
struct pnt{
int hd;
int fa;
int f;
int tp;
int wgt;
int mxs;
int dis;
bool vis;
int roota;
int rootp;
}p[N];
struct trnt{
int ls;
int rs;
int val;
}tr[];
struct ent{
int twd;
int lst;
}e[N<<];
int n,m;
int cnt;
int siz;
int root;
int size;
int maxsize;
char cmd[];
void ade(int f,int t)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
void Basic_dfs(int x,int f)
{
p[x].dis=p[f].dis+;
p[x].f=f;
p[x].wgt=;
int maxs=-;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f)
continue;
Basic_dfs(to,x);
p[x].wgt+=p[to].wgt;
if(maxs<p[to].wgt)
{
maxs=p[to].wgt;
p[x].mxs=to;
}
}
return ;
}
void Build_dfs(int x,int top)
{
if(!x)
return ;
p[x].tp=top;
Build_dfs(p[x].mxs,top);
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==p[x].mxs||to==p[x].f)
continue;
Build_dfs(to,to);
}
return ;
}
int Lca(int x,int y)
{
while(p[x].tp!=p[y].tp)
{
if(p[p[x].tp].dis<p[p[y].tp].dis)
std::swap(x,y);
x=p[p[x].tp].f;
}
if(p[x].dis>p[y].dis)
std::swap(x,y);
return x;
}
int Dis(int x,int y)
{
int z=Lca(x,y);
return p[x].dis+p[y].dis-*p[z].dis;
}
void grc_dfs(int x,int f)
{
p[x].wgt=;
int maxs=-;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f||p[to].vis)
continue;
grc_dfs(to,x);
p[x].wgt+=p[to].wgt;
if(maxs<p[to].wgt)
maxs=p[to].wgt;
}
maxs=std::max(maxs,size-p[x].wgt);
if(maxs<maxsize)
{
root=x;
maxsize=maxs;
}
return ;
}
void bin_dfs(int x,int f)
{
p[x].fa=f;
p[x].vis=true;
int tmp=size;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].vis)
continue;
root=;
if(p[x].wgt>p[to].wgt)
size=p[to].wgt;
else
size=tmp-p[x].wgt;
maxsize=0x3f3f3f3f;
grc_dfs(to,to);
bin_dfs(root,x);
}
return ;
}
void update(int &spc,int l,int r,int ll,int rr,int v)
{
if(ll>r||l>rr)
return ;
if(!spc)
spc=++siz;
if(ll<=l&&r<=rr)
{
tr[spc].val+=v;
return ;
}
int mid=(l+r)>>;
update(tr[spc].ls,l,mid,ll,rr,v);
update(tr[spc].rs,mid+,r,ll,rr,v);
return ;
}
int query(int spc,int l,int r,int pos)
{
if(!spc)
return ;
int ans=tr[spc].val;
if(l==r)
return ans;
int mid=(l+r)>>;
if(pos<=mid)
ans+=query(tr[spc].ls,l,mid,pos);
else
ans+=query(tr[spc].rs,mid+,r,pos);
return ans;
}
void Update(int x,int k,int val)
{
update(p[x].rootp,,n-,,k,val);
for(int i=x;p[i].fa;i=p[i].fa)
{
int d=Dis(x,p[i].fa);
if(k<d)
continue;
update(p[p[i].fa].rootp,,n-,,k-d,val);
update(p[i].roota,,n-,,k-d,val);
}
return ;
}
int Query(int x)
{
int ans=query(p[x].rootp,,n-,);
for(int i=x;p[i].fa;i=p[i].fa)
{
int d=Dis(x,p[i].fa);
ans+=query(p[p[i].fa].rootp,,n-,d)-query(p[i].roota,,n-,d);
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
ade(a,b);
ade(b,a);
}
Basic_dfs(,);
Build_dfs(,);
root=;
size=n;
maxsize=0x3f3f3f3f;
grc_dfs(,);
bin_dfs(root,);
while(m--)
{
scanf("%s",cmd+);
if(cmd[]=='M')
{
int x,k,v;
scanf("%d%d%d",&x,&k,&v);
Update(x,k,v);
}else{
int x;
scanf("%d",&x);
printf("%d\n",Query(x));
}
}
return ;
}
BZOJ4372: 烁烁的游戏(动态点分治)的更多相关文章
- BZOJ4372烁烁的游戏——动态点分治+线段树(点分树套线段树)
题目描述 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠.题意:给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠.烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠.皮皮鼠会被 ...
- [bzoj4372] 烁烁的游戏 [动态点分治+线段树+容斥原理]
题面 传送门 思路 观察一下题目,要求的是修改"距离点$u$的距离一定的点权值",那这个就不能用传统的dfs序类算法+线段树维护,因为涉及到向父亲回溯的问题 看到和树上距离相关的东 ...
- [BZOJ4372]烁烁的游戏(动态点分治+线段树)
和[BZOJ3730]震波几乎一样,每个点建两棵线段树分别代表它的管辖范围内以它为LCA的路径的贡献和它对父亲的贡献. 注意点分树上的点的距离在原树上不单调,所以不能有若距离超出限制就break之类的 ...
- 【BZOJ4372】烁烁的游戏 动态树分治+线段树
[BZOJ4372]烁烁的游戏 Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠.题意:给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠.烁烁他每次会跳到一个节点u,把周围与他距 ...
- 【bzoj4372】烁烁的游戏 动态点分治+线段树
题目描述 给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:Q x:询问x的点权.M x d w:将树上与节点x距离不超过d的节点的点权均加上w. 输入 第一行两个正整数:n,m接下来的n-1 ...
- bzoj 4372: 烁烁的游戏 动态点分治_树链剖分_线段树
[Submit][Status][Discuss] Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳 ...
- bzoj 4372 烁烁的游戏——动态点分治+树状数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 和 bzoj 3070 震波 是一个套路.注意区间修改的话,树状数组不能表示 dis ...
- bzoj 4372 烁烁的游戏 —— 动态点分治+树状数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 本以为和 bzoj3730 一样,可以直接双倍经验了: 但要注意一下,树状数组不能查询 ...
- BZOJ4372: 烁烁的游戏【动态点分治】
Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w ...
随机推荐
- EBS 第一个项目 学习总结 ---- 发运模块
EBS 组织架构: (一)业务组(BG) (二)法律实体(LE) (三)业务实体(OU) (四)库存组织(INV) (五)公司成本中心(Cost Center) (六)HR组织 (七)多组织接入控制 ...
- 大型网站架构之JAVA中间件
中间件就是在大型网站中,帮助各子模块间实现互相访问,消息共享或统一访问等功能的软件产品.常见的有: 远程服务框架中间件:主要解决各子模块之间互相访问的问题. 消息队列中间件:主要解决各子模之间消息共享 ...
- 27.C语言宽字符操作
#include <locale.h> setlocale(LC_ALL, "zh-CN"); wchar_t wch = L'我'; putwchar(wch); # ...
- 25.Detours劫持技术
Detours可以用来实现劫持,他是微软亚洲研究院开发出来的工具,要实现它首先需要安装Detours. 安装地址链接:https://pan.baidu.com/s/1eTolVZs 密码:uy8x ...
- Linux 桌面的 Dock 类程序
1.Cairo-Dock是一个Dock类软件,它支持OpenGL.提供动画及视觉效果的插件.新的Applet.重写配置面板.新增主题等功能. 2.Docky是从GNOME Do项目剥离出来的一个Doc ...
- 一个Web报表项目的性能分析和优化实践(六):设置MySQL的最大连接数(max_connections)
在上一篇文章中"一个Web报表项目的性能分析和优化实践(二):MySQL数据库连接不够用(TooManyConnections)问题的一次分析和解决案例"提到,项目中新增几个数据库 ...
- leetcode第一刷_Rotate List
我提交了好多次,错误莫名其妙的,到后来才明确过来.原来我把题目给理解错了. 这个题的意思不是说让你把最后的那k个位置的元素移到前面来,这样的问题的做法就是用两个指针,先让一个走.走到一定的长度之后两个 ...
- ios—项目开发需求文档
电子商务产品项目需求方案 模块 标准 接入方式 后台(大致需求说明) 前端 购 实物 多商户接入,可支付商品: 基础功能 功能说明 所有须要 Lbs .城市选择,分享.商区.搜索.返回.关闭 LBS: ...
- AVEVA PDMS Text Tool
AVEVA PDMS Text Tool eryar@163.com 网上有个文字工具插件,可以在PDMS中创建三维的字母.数字,不过不能创建中文.所以开发一个小工具,可以在PDMS中创建任意文字,如 ...
- mongodb官网文档阅读笔记:write concern
write concern保证了mongodb写操作的级别,不同的write concern设置相应了不同级别的写操作.设置的级别越高.那么写操作的性能的持久化做得越好,可是写性能也就越差. mong ...