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 ...
随机推荐
- Android视图载入到窗体的过程分析
上一篇博客Android中Handler原理在讲到Handler的时候谈到了android的Activity启动是怎样运行到onCreate方法的,这篇主要从onCreate方法里面我们必需要写的方法 ...
- 3.AngularJS-过滤器
转自:https://www.cnblogs.com/best/p/6225621.html 二.过滤器 使用过滤器格式化数据,变换数据格式,在模板中使用一个插值变量.语法格式如下: {{ expre ...
- 15.Intellij中配置jdk/tomcat/maven
转自:https://blog.csdn.net/u010414666/article/details/44465905 继上一篇安装好了Intellij之后,我们可以对Intellij,做一些简单的 ...
- SQL Server 2000数据库备份与恢复图解
SQL Server 2000数据库备份与恢复图解 四个步骤:1.安装sql server 2000 2.数据库设置: 3.建立自动备份 4.还原数据库 具体图片见附件 本文出自 "李 ...
- @Html.Raw() 方法输出带有html标签的字符串
@Html.Raw() 方法输出带有html标签的字符串,如:@Html.Raw("<div style='color:red'>输出字符串</div>") ...
- 注解:@SuppressWarning()的用法
@SuppressWarning() 作用:J2SE 提供的一个批注或者注解.该批注的作用是给编译器一条指令,忽略这些警告信息. 常用:unchecked,serial. 1.如果传入多种情况,这几种 ...
- python关于sorted里面key,reverse以及lamdba,operator这几个鸟人
关于sorted: help里给的解释 >>> help(sorted) Help on built-in function sorted in module __builti ...
- jQuery对checkbox选中和取消选中操作
最近做项目发现jQuery对checkbox的全选和非全选操作只有第一次生效,以后就不生效了,不知道是不是jQuery版本库的问题,最终找到了一个解决方案: 把原来的下面这两句: $('input') ...
- linux 配置全局jdk环境
1.在usr/local下新建software文件夹(mkdir software),将下载的jdk和tomcat放在此文件夹下 2.解压 tar -xzvf jdk-8u191-linux-x64. ...
- 【转】Flash AS3.0 中的自定义事件
原文 http://www.cnblogs.com/acpp/archive/2010/10/19/1855670.html package { import flash.events.Event; ...