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 ...
随机推荐
- Visual Studio2008 和2010 执行程序出现的黑框马上消失解决方法
1 在程序最后加 system("PAUSE"); 要注意包括头文件#include"stdlib.h" //system须要调用这个 ...
- JAVA并发-内置锁和ThreadLocal
上一篇博客讲过,当多个线程访问共享的可变变量的时候,可以使用锁来进行线程同步.那么如果线程安全性存在的3个前提条件不同时存在的话,自然就不需要考虑线程安全性了.或者说如果我们能够将某个共享变量变为局部 ...
- poj--1637--Sightseeing tour(网络流,最大流判断混合图是否存在欧拉图)
Sightseeing tour Time Limit: 1000MS Memory Limit: 10000KB 64bit IO Format: %I64d & %I64u Sub ...
- 流量数据iftop命令
yum install flex byacc libpcap ncurses ncurses-devel libpcap-devel tar zxvf iftop-0.17.tar.gz cd ift ...
- dubbo问题求解
各位大牛好,小弟公司开发中遇到一个很奇怪的问题望有大神指教一下,实在是已经搞了3天了一点头绪没有,公司使用的是eclipse+maven+zookeper+dubbo主要是dubbo的问题,刚开始使用 ...
- BZOJ 1578 DP
思路:裸的完全背包 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> ...
- BZOJ 1193 搜索+贪心
预处理出100*100以内的最优解 贪心走日 判断是0*4还是2*4 搞定 //By SiriusRen #include <queue> #include <cstdio> ...
- axure中使用HighCharts模板制作统计图表
一. 步骤: 1.在axure中新建页面,发布并生成html文件: 2.将HighCharts文件夹,拷贝到生成的html文件中: 3.拖拽“内部框架组件”到界面中 4.双击界面中的内部框架,设置链接 ...
- SQL try catch处理
ALTER PROC usp_AccountTransaction @AccountNum INT, @Amount DECIMAL AS BEGIN BEGIN TRY --Start the Tr ...
- 如何更新 CentOS 镜像源
话不多说, 直接上教程. 首先备份/etc/yum.repos.d/CentOS-Base.repo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.rep ...