烁烁的游戏 题目大意:

给你一棵$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 烁烁的游戏/震波 (动态点分治+线段树)的更多相关文章

  1. BZOJ4372 烁烁的游戏(动态点分治+线段树)

    建出点分树,每个节点维护其作为点分树上lca对子树内点的贡献,线段树维护即可,同时另开一个线段树以减掉父亲重复的贡献. #include<iostream> #include<cst ...

  2. 【bzoj3730】震波 动态点分治+线段树

    题目描述 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时代的发展,城市 ...

  3. BZOJ3730震波——动态点分治+线段树(点分树套线段树)

    题目描述 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时代的发展,城市 ...

  4. 【BZOJ4372】烁烁的游戏(动态点分治)

    [BZOJ4372]烁烁的游戏(动态点分治) 题面 BZOJ 大意: 每次在一棵书上进行操作 1.将离某个点u的距离不超过d的点的权值加上w 2.询问单点权值 题解 这题和前面那一道震波几乎是一模一样 ...

  5. 【bzoj4372】烁烁的游戏 动态点分治+线段树

    题目描述 给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:Q x:询问x的点权.M x d w:将树上与节点x距离不超过d的节点的点权均加上w. 输入 第一行两个正整数:n,m接下来的n-1 ...

  6. 【loj6145】「2017 山东三轮集训 Day7」Easy 动态点分治+线段树

    题目描述 给你一棵 $n$ 个点的树,边有边权.$m$ 次询问,每次给出 $l$ .$r$ .$x$ ,求 $\text{Min}_{i=l}^r\text{dis}(i,x)$ . $n,m\le ...

  7. BZOJ4372烁烁的游戏——动态点分治+线段树(点分树套线段树)

    题目描述 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠.题意:给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠.烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠.皮皮鼠会被 ...

  8. [bzoj4372] 烁烁的游戏 [动态点分治+线段树+容斥原理]

    题面 传送门 思路 观察一下题目,要求的是修改"距离点$u$的距离一定的点权值",那这个就不能用传统的dfs序类算法+线段树维护,因为涉及到向父亲回溯的问题 看到和树上距离相关的东 ...

  9. bzoj3730 震波 [动态点分治,树状数组]

    传送门 思路 如果没有强制在线的话可以离线之后CDQ分治随便搞. 有了强制在线之后--可能可以二维线段树?然而我不会算空间. 然后我们莫名其妙地想到了动态点分治,然后这题就差不多做完了. 点分树有一个 ...

随机推荐

  1. 当li设置为line-block时,元素之间出现间隙的原因和解决方法

    原因 因为浏览器默认把inline元素之间的空白符(Tab.空格.换行)渲染成一个空格.而如下述代码,两个li元素之间的换行符被渲染成一个空格,则元素之间产生了间隙. 用Chrome浏览器将场景模拟出 ...

  2. python_格式化拼接、format,编码、解码

    一.格式化拼接.format 1.字符串拼接 name = "Monica", age = 16 print("姓名"+name+“年龄”+age+" ...

  3. python第二周:数据类型、列表、字典

    1.模块初识: sys模块: import sys print(sys.path) #path打印环境变量--> ['F:\\python学习\\projects\\s14\\day2', 'F ...

  4. 【 AIM Tech Round 5 (rated, Div. 1 + Div. 2) C】Rectangles

    [链接] 我是链接,点我呀:) [题意] 给你n个矩形. 让你找出一个点(x,y) 使得这个点在其中至少(n-1)个矩形中. [题解] 若干个矩形交在一起的话. 它们所有的公共区域也会是一个矩形. 这 ...

  5. 参数化取值策略Random

    1.Random+Each iteration,跟顺序读取的结果唯一不同的就是这里是随机读取,取值是每次迭代取值   2.Random+Each occurrence,随机取值更新方式     3.R ...

  6. 洛谷——P1030 求先序排列

    https://www.luogu.org/problem/show?pid=1030#sub 题目描述 给出一棵二叉树的中序与后序排列.求出它的先序排列.(约定树结点用不同的大写字母表示,长度< ...

  7. HDU 2371

    知道了怎么置换之后,就可以用矩阵来置换了,但这道题一直关于置换的地方读不明白. #include <iostream> #include <cstdio> #include & ...

  8. EJB学习(四)——Enterprise Bean(企业Bean)和Entity Bean(实体Bean)

        一.为什么使用EJB ? 企业Bean执行在EJB容器中.企业Bean实际上就是一个封装了业务逻辑的Java类,那么我们为什么要使用EJB呢 ? 1.最重要的原因:分布式.简要的说,分布式能够 ...

  9. HDU TIANKENG’s rice shop(模拟)

    HDU 4884 TIANKENG's rice shop 题目链接 题意:模拟题.转一篇题意 思路:就模拟就可以.注意每次炒完之后就能够接单 代码: #include <cstdio> ...

  10. [Android 性能优化系列]内存之基础篇--Android怎样管理内存

    大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地 ...