BZOJ 4372/3370 烁烁的游戏/震波 (动态点分治+线段树)
烁烁的游戏 题目大意:
给你一棵$n$个节点的树,有$m$次操作,询问某个节点的权值,或者将与某个点$x$距离不超过$d$的所有节点的权值都增加$w$
动态点分裸题
每个节点开一棵权值线段树
对于修改操作,它从$x$开始,像一个涟漪扩散,对它周围与它距离$\leq d$的所有节点造成$w$点贡献
为了记录这个操作的贡献,我们寻找树分治每一层中 包含这个节点的那个点分树的重心$root$
在$root$处记录贡献,开一棵动态开点权值线段树,记录与这个节点距离为$d$的贡献总和,显然在$root$周围扩散范围是$d-dis(x,root)$
还要去掉包含$x$子树的贡献,所以每个节点要再开一个,记录对于父重心需要去掉的贡献
每次查询都沿着点分重心往上跳,因为修改的过程是在线段树上打差分,所以在当前重心查询$d-dis(x,root)$的后缀和即可
由于每次修改都要不断网上跳重心,一共要修改$log$次,每次都要求距离,所以采用欧拉序求$LCA$减小常数
空间是$O(nlog^{2}n)$的,容易被卡,记录当前节点最大能扩散的范围,即当前节点接管的那部分子树内节点的最大深度,非常有效地优化了空间
实在是讲不太明白,大家可以看代码
#include <map>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 101000
#define ll long long
#define dd double
#define inf 0x3f3f3f3f3f3f3f3fll
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
} struct SEG{
int sum[N1*],ls[N1*],rs[N1*],rm[N1],rf[N1],tot;
void pushup(int rt){sum[rt]=sum[ls[rt]]+sum[rs[rt]];}
void update(int x,int l,int r,int &rt,int w)
{
if(!rt) rt=++tot;
if(l==r) {sum[rt]+=w;return;}
int mid=(l+r)>>;
if(x<=mid) update(x,l,mid,ls[rt],w);
else update(x,mid+,r,rs[rt],w);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(!rt) return ;
if(L<=l&&r<=R) return sum[rt];
int mid=(l+r)>>,ans=;
if(L<=mid) ans+=query(L,R,l,mid,ls[rt]);
if(R>mid) ans+=query(L,R,mid+,r,rs[rt]);
return ans;
}
}s; struct Edge{
int to[N1<<],nxt[N1<<],head[N1],cte;
void ae(int u,int v)
{cte++;to[cte]=v,nxt[cte]=head[u],head[u]=cte;}
}e; int n,m,T;
namespace tr{
int dep[N1],ff[N1<<][],st[N1],id[N1<<],lg[N1<<],tot;
void dfs1(int u,int dad)
{
id[++tot]=u; st[u]=tot; ff[tot][]=u;
for(int j=e.head[u];j;j=e.nxt[j])
{
int v=e.to[j]; if(v==dad) continue;
dep[v]=dep[u]+; dfs1(v,u); id[++tot]=u; ff[tot][]=u;
}
}
void get_st()
{
int i,j;
for(lg[]=,i=;i<=tot;i++) lg[i]=lg[i>>]+;
for(j=;j<=lg[tot];j++)
for(i=;i+(<<j)-<=tot;i++)
ff[i][j]=dep[ ff[i][j-] ]<dep[ ff[i+(<<(j-))][j-] ]?ff[i][j-]:ff[i+(<<(j-))][j-];
}
int dis(int x,int y)
{
int tx=min(st[x],st[y]),ty=max(st[x],st[y]),L=ty-tx+;
int fa=dep[ ff[tx][lg[L]] ]<dep[ ff[ty-(<<lg[L])+][lg[L]] ]?ff[tx][lg[L]]:ff[ty-(<<lg[L])+][lg[L]];
return dep[x]+dep[y]-*dep[fa];
}
void init(){dfs1(,-);get_st();}
}; using tr::dis; int ms[N1],sz[N1],dep[N1],mad[N1],use[N1],fa[N1],tsz,G;
void dfs(int u,int dad,int g)
{
mad[g]=max(mad[g],dep[u]); sz[u]=;
for(int j=e.head[u];j;j=e.nxt[j])
{
int v=e.to[j]; if(v==dad||use[v]) continue;
dep[v]=dep[u]+; dfs(v,u,g); sz[u]+=sz[v];
}
}
void gra(int u,int dad)
{
sz[u]=; ms[u]=;
for(int j=e.head[u];j;j=e.nxt[j])
{
int v=e.to[j]; if(use[v]||v==dad) continue;
gra(v,u); sz[u]+=sz[v]; ms[u]=max(ms[u],sz[v]);
}
ms[u]=max(ms[u],tsz-sz[u]);
if(ms[u]<ms[G]) G=u;
}
void main_dfs(int u)
{
use[u]=; dep[u]=; dfs(u,-,u);
for(int j=e.head[u];j;j=e.nxt[j])
{
int v=e.to[j]; if(use[v]) continue;
G=; tsz=sz[v]; gra(v,-); fa[G]=u;
main_dfs(G);
}
}
void modify(int x,int K,int w)
{
int i,D;
for(i=x;i;i=fa[i])
{
D=dis(x,i);
if(D<=K) s.update(min(mad[i],K-D),,mad[i],s.rm[i],w);
if(!fa[i]) break;
D=dis(x,fa[i]);
if(D<=K) s.update(min(mad[fa[i]],K-D),,mad[fa[i]],s.rf[i],w);
}
}
int query(int x)
{
int i,D,ans=;
for(i=x;i;i=fa[i])
{
D=dis(x,i);
if(D<=mad[i]) ans+=s.query(D,mad[i],,mad[i],s.rm[i]);
if(!fa[i]) break;
D=dis(x,fa[i]);
if(D<=mad[fa[i]]) ans-=s.query(D,mad[fa[i]],,mad[fa[i]],s.rf[i]);
}
return ans;
} int main()
{
scanf("%d%d",&n,&m);
int i,j,x,y,w,ans=;
for(i=;i<n;i++) x=gint(), y=gint(), e.ae(x,y), e.ae(y,x);
tr::init();
ms[]=tsz=n; G=; gra(,-); gra(G,-);
main_dfs(G); char str[];
for(i=;i<=m;i++)
{
scanf("%s",str);
if(str[]=='M'){
x=gint(); y=gint(); w=gint();
modify(x,y,w);
}else{
x=gint();
ans=query(x);
printf("%d\n",ans);
}
}
return ;
}
震波那道题和这道题非常像,只不过是点的修改和子树的查询
但由于我一直被卡常,没脸放代码了qwq
BZOJ 4372/3370 烁烁的游戏/震波 (动态点分治+线段树)的更多相关文章
- BZOJ4372 烁烁的游戏(动态点分治+线段树)
建出点分树,每个节点维护其作为点分树上lca对子树内点的贡献,线段树维护即可,同时另开一个线段树以减掉父亲重复的贡献. #include<iostream> #include<cst ...
- 【bzoj3730】震波 动态点分治+线段树
题目描述 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时代的发展,城市 ...
- BZOJ3730震波——动态点分治+线段树(点分树套线段树)
题目描述 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时代的发展,城市 ...
- 【BZOJ4372】烁烁的游戏(动态点分治)
[BZOJ4372]烁烁的游戏(动态点分治) 题面 BZOJ 大意: 每次在一棵书上进行操作 1.将离某个点u的距离不超过d的点的权值加上w 2.询问单点权值 题解 这题和前面那一道震波几乎是一模一样 ...
- 【bzoj4372】烁烁的游戏 动态点分治+线段树
题目描述 给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:Q x:询问x的点权.M x d w:将树上与节点x距离不超过d的节点的点权均加上w. 输入 第一行两个正整数:n,m接下来的n-1 ...
- 【loj6145】「2017 山东三轮集训 Day7」Easy 动态点分治+线段树
题目描述 给你一棵 $n$ 个点的树,边有边权.$m$ 次询问,每次给出 $l$ .$r$ .$x$ ,求 $\text{Min}_{i=l}^r\text{dis}(i,x)$ . $n,m\le ...
- BZOJ4372烁烁的游戏——动态点分治+线段树(点分树套线段树)
题目描述 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠.题意:给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠.烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠.皮皮鼠会被 ...
- [bzoj4372] 烁烁的游戏 [动态点分治+线段树+容斥原理]
题面 传送门 思路 观察一下题目,要求的是修改"距离点$u$的距离一定的点权值",那这个就不能用传统的dfs序类算法+线段树维护,因为涉及到向父亲回溯的问题 看到和树上距离相关的东 ...
- bzoj3730 震波 [动态点分治,树状数组]
传送门 思路 如果没有强制在线的话可以离线之后CDQ分治随便搞. 有了强制在线之后--可能可以二维线段树?然而我不会算空间. 然后我们莫名其妙地想到了动态点分治,然后这题就差不多做完了. 点分树有一个 ...
随机推荐
- jQuery.extend()的合并对象功能
jQuery.extend( [ deep ], target, object1, [ objectN ] )合并对象到第一个对象 //deep为boolean类型,其它参数为object类型 var ...
- luogu 4884 多少个1 (BSGS)
很有意思的一个签到题 然而考场上并没有切掉 $1111...111=K(mod\;m)$ $10^{x}=9K+1(mod\;m)$ 用$BSGS$求解即可 模数爆了$int$,需要快速乘,然而模数是 ...
- spring和struts整合
整合准备:导入jar包 如果只是访问action,没有做数据库方面的操作的话 只需要导入下面的jar spring相关jar 以及struts相关jar包 整合过程: 用到了struts所以需要在we ...
- HDU 1475 Pushing Boxes
Pushing Boxes Time Limit: 2000ms Memory Limit: 131072KB This problem will be judged on PKU. Original ...
- BA-siemens-PXC模块调试
PXC24模块写地址步骤: 1.制作一根HMI线: 2.通过HMI+232转USB转接卡连接模块: 3.根据已经做好的系统架构表来配置模块: 写模块之前不要忘了格式化模块,主要命令如下: 视频教程:h ...
- iOS_21团购_地图功能
终于效果图: 右下角的回到用户位置button: MapController控制器, 是主控制器左側dock上面的[地图]button相应的控制器, 继承自ShowDealDetailControll ...
- 【scikit-learn】交叉验证及其用于參数选择、模型选择、特征选择的样例
内容概要¶ 训练集/測试集切割用于模型验证的缺点 K折交叉验证是怎样克服之前的不足 交叉验证怎样用于选择调节參数.选择模型.选择特征 改善交叉验证 1. 模型验证回想¶ 进行模型验证的一个重要目 ...
- insmod hello.ko -1 Invalid module format最简单的解决的方法
在下也是从网上搜索到的这样的解决的方法. 遇到这样的情况后,通过dmesg看一下内核日志. 假设发现有例如以下日志.那就好办了. hello: version magic '2.6.33.3 ' sh ...
- MyEclipse2015安装SVN插件
一.下载SVN插件subclipse 下载地址:http://subclipse.tigris.org/servlets/ProjectDocumentList?folderID=2240 在打开的网 ...
- TS2
//还要注意的是,在构造函数的参数上使用public等同于创建了同名的成员变量. class Student { fullName: string; constructor(public firstN ...