震波——动态点分治+线段树
题目
【题目描述】
在一片土地上有 $N$ 个城市,通过 $N-1$ 条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为 $1$,其中第 $i$ 个城市的价值为 $value[i]$。
不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
接下来你需要在线处理 $M$ 次操作:
- $0~x~k$ 表示发生了一次地震,震中城市为 $x$ ,影响范围为 $k$ ,所有与 $x$ 距离不超过 $k$ 的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
- $1~x~y$ 表示第$x$个城市的价值变成了 $y$ 。
为了体现程序的在线性,操作中的 $x$ 、$y$ 、$k$ 都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为 $0$ 。
【输入格式】
第一行包含两个正整数 $N$ 和 $M$ 。
第二行包含 $N$ 个正整数,第 $i$ 个数表示 $value[i]$ 。
接下来 $N-1$ 行,每行包含两个正整数$u,v$,表示 $u$ 和 $v$ 之间有一条无向边。
接下来 $M$ 行,每行包含三个数,表示 $M$ 次操作。
【输出格式】
包含若干行,对于每个询问输出一行一个正整数表示答案。
【样例输入】
8 1
1 10 100 1000 10000 100000 1000000 10000000
1 2
1 3
2 4
2 5
3 6
3 7
3 8
0 3 1
【样例输出】
11100101
【数据范围与提示】
$1 \le N,M \le 100000$
$1 \le u,v,x \le N $
$1 \le value[i],y \le 10000 $
$ 0 \le k \le N-1 $
题解
要求树上和一个点距离不超过 $k$ 的所有点,很容易想到动态点分治
开 $ n $ 棵权值线段树,记录当前点分中心距离为 $ v $ 的点的个数
考虑在点分树上查询,会发现在 $ x $ 统计过答案的点有可能在 $ fa[x] $ 上也被统计
考虑容斥,再开 $ n $ 棵线段树,记录从当前点分中心 $ x $ 经过 $ fa[x] $ 距离为 $ v $ 的权值和,查询时扣掉即可
时间效率:$ O(nlog^2 n) $
代码
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define il inline 4 #define re register 5 #define _(d) while(d(isdigit(ch=getchar()))) 6 using namespace std; 7 il int R(){ 8 int x;bool f=1;char ch;_(!)if(ch=='-')f=0;x=ch^48; 9 _()x=(x<<3)+(x<<1)+(ch^48);return f?x:-x;} 10 const int N=2e5+10; 11 int n,m,ans,f[N],top[N],dep[N],sz[N],son[N],head[N],cnt,Mx,Rt,Sz,fa[N],siz[N],val[N],rot[N<<1],tot; 12 bool vis[N]; 13 struct seg{int ls,rs,v;}tr[N<<6]; 14 struct edge{int to,nex;}e[N<<1]; 15 il void add(int s,int t){e[++cnt]=(edge){t,head[s]},head[s]=cnt;} 16 il void dfs(int x,int far){ 17 f[x]=far,sz[x]=1,dep[x]=dep[far]+1; 18 for(re int v,k=head[x];k;k=e[k].nex) 19 if((v=e[k].to)!=far){ 20 dfs(v,x),sz[x]+=sz[v]; 21 if(sz[v]>sz[son[x]])son[x]=v; 22 } 23 return; 24 } 25 il void DFS(int x,int far){ 26 top[x]=far; 27 if(son[x])DFS(son[x],far); 28 for(re int k=head[x],v;k;k=e[k].nex) 29 if((v=e[k].to)!=f[x]&&v!=son[x]) 30 DFS(v,v); 31 } 32 il int lca(int x,int y){ 33 while(top[x]^top[y]){ 34 if(dep[top[x]]<dep[top[y]])swap(x,y); 35 x=f[top[x]]; 36 } 37 return dep[x]<dep[y]?x:y; 38 } 39 il int get(int u,int v){return dep[u]+dep[v]-2*dep[lca(u,v)];} 40 il void getrot(int u,int far){ 41 int mx=0;siz[u]=1; 42 for(re int k=head[u],v;k;k=e[k].nex) 43 if((v=e[k].to)!=far&&!vis[v]) 44 getrot(v,u),siz[u]+=siz[v],mx=max(mx,siz[v]); 45 mx=max(mx,Sz-siz[u]); 46 if(mx<Mx)Mx=mx,Rt=u; 47 return; 48 } 49 il int getsize(int u,int far){ 50 siz[u]=1; 51 for(re int k=head[u],v;k;k=e[k].nex) 52 if((v=e[k].to)!=far&&!vis[v]) 53 siz[u]+=getsize(v,u); 54 return siz[u]; 55 } 56 void slove(int u,int far){ 57 Mx=1e9,getrot(u,0),vis[Rt]=1; 58 fa[Rt]=far,far=Rt; 59 for(re int k=head[Rt],v;k;k=e[k].nex) 60 if(!vis[v=e[k].to])Sz=getsize(v,0),slove(v,far); 61 } 62 #define Ls tr[rt].ls 63 #define Rs tr[rt].rs 64 il void change(int &rt,int l,int r,int k,int x){ 65 if(!rt)rt=++tot; 66 tr[rt].v+=x; 67 if(l==r)return; 68 int mid=(l+r)>>1; 69 if(k<=mid)change(Ls,l,mid,k,x); 70 else change(Rs,mid+1,r,k,x); 71 return; 72 } 73 il int query(int rt,int l,int r,int qr){ 74 if(!rt)return 0; 75 if(qr>=r)return tr[rt].v; 76 int mid=(l+r)>>1,res=0; 77 if(qr>mid)res=tr[Ls].v+query(Rs,mid+1,r,qr); 78 else res=query(Ls,l,mid,qr); 79 return res; 80 } 81 il void update(int x,int v){ 82 change(rot[x],0,n,0,v); 83 for(re int i=x;fa[i];i=fa[i]){ 84 int dis=get(x,fa[i]); 85 change(rot[fa[i]],0,n,dis,v); 86 change(rot[i+n],0,n,dis,v); 87 } 88 } 89 il int ask(int x,int y){ 90 int res=query(rot[x],0,n,y); 91 for(re int i=x;fa[i];i=fa[i]){ 92 int dis=get(x,fa[i]); 93 if(dis>y)continue; 94 res+=query(rot[fa[i]],0,n,y-dis)-query(rot[i+n],0,n,y-dis); 95 } 96 return res; 97 } 98 int main(){ 99 n=R(),m=R(); 100 for(re int i=1;i<=n;i++)val[i]=R(); 101 for(re int i=1,u,v;i<n;i++) 102 u=R(),v=R(),add(u,v),add(v,u); 103 dfs(1,0),DFS(1,1),Sz=n,slove(1,0); 104 for(re int i=1;i<=n;i++)update(i,val[i]); 105 for(re int i=1;i<=m;i++){ 106 int op=R(),x=R()^ans,y=R()^ans; 107 if(op)update(x,y-val[x]),val[x]=y; 108 else printf("%d\n",ans=ask(x,y)); 109 } 110 return 0; 111 }
View Code
转载于:https://www.cnblogs.com/chmwt/p/10661287.html
震波——动态点分治+线段树相关推荐
- 【bzoj4372】烁烁的游戏 动态点分治+线段树
题目描述 给一颗n个节点的树,边权均为1,初始点权均为0,m次操作: Q x:询问x的点权. M x d w:将树上与节点x距离不超过d的节点的点权均加上w. 输入 第一行两个正整数:n,m 接下来的 ...
- bzoj4372 烁烁的游戏 动态点分治+线段树
Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠 ...
- BZOJ4372 烁烁的游戏(动态点分治+线段树)
建出点分树,每个节点维护其作为点分树上lca对子树内点的贡献,线段树维护即可,同时另开一个线段树以减掉父亲重复的贡献. #include<iostream> #include<cst ...
- 【BZOJ4372】烁烁的游戏 动态树分治+线段树
[BZOJ4372]烁烁的游戏 Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围 ...
- [BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA]
[BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA] 题目大意: 给定一颗nn个节点的树,边权均为11,初始每个点权值为00 . 其中操作QQ xx询问x点的点权,操作 MM xx dd ...
- 【线段树合并】解题报告:luogu P4556雨天的尾巴 (树上对点差分 + 动态开点 + 线段树合并)线段树合并模板离线/在线详解
题目链接:雨天的尾巴 本题本身是一个非常简单的一道树上差分的模板题,但是由于变态的数据范围,我们直接用数组是存不下的(本来使用一颗普通的线段树直接维护最大值即可.但是本题的空间只有128MB,直接按照 ...
- 洛谷P3960 列队(动态开节点线段树)
题意 题目链接 Sol 看不懂splay..,看不懂树状数组... 只会暴力动态开节点线段树 观察之后不难发现,我们对于行和列需要支持的操作都是相同的:找到第\(k\)大的元素并删除,在末尾插入一个元 ...
- 动态开点线段树(多棵线段树)的内存分配与回收
前言 线段树,是一个很好用的能支持O(logn)区间操作的数据结构,随着做一些稍微烦一点的题,有时候会发现有些情况要开一个数组的线段树,更有甚者要树套树,而在很多情况下线段树就不能把所有点都开满了(否 ...
- 洛谷T44252 线索_分治线段树_思维题
分治线段树,其实就是将标记永久化,到最后再统一下传所有标记. 至于先后顺序,可以给每个节点开一个时间戳. 一般地,分治线段树用于离线,只查询一次答案的题目. 本题中,标记要被下传 222 次. Cod ...
最新文章
- 「GNN,简直太烂了」,一位Reddit网友的深度分析火了
- ffmpeg4 读取图片编码
- 多线程读取矩阵文件+多线程矩阵乘法(C++实现)
- RFID和WiFi定位技术的比较
- 高手教你如何用香技巧香水达人教你用香省钱法 - 生活至上,美容至尚!
- 洛谷 深基 第4部分 基础数学与数论(19-21课)
- 项目管理学习 ---- 项目管理沟通技巧
- 无线破解攻击工具使用详解
- Kaspersky Anti-Virus NDIS Filter导致的网络故障一例
- 解决git Please use -- (and optionally --no-guess) to disambiguate
- CentOS7 Linux引导修复
- OFDM峰均比抑制matlab,一种降低OFDM峰均比的解决方法
- python 将JS(JavaScript)的json格式字符串转换为python的字典格式
- 表白神器:DIY舵机版无聊小盒 3D打印
- 张景明:方剂【方歌】——祛暑剂
- javaWeb项目部署到远程服务器(windows服务器)
- 模拟工作室机架音频插件
- PVF(PGI Visual Fortran) 安装以及openacc在linux和window下调用
- 视频点播服务器性能,基于排队论的视频点播系统性能分析
- 深度学习基础——多层感知机