bzoj3730. 震波
动态点分治
考虑从每一个"块"里找到距离k范围内的点的和
为了去重,
每个x维护两个线段树:(都是关于自己分治树子树的点)
1.下标为距离x的距离,权值为val的
2.下标为距离x的分治树father的距离,权值为val
这样,统计的时候
计算分治树祖先块的时候,把从自己那里出来的块的东西再减去
注意:
1.点分治nowrt是全局变量,所以divi这一层用tmp额外记录一下,否则回溯回来再下去的时候,nowrt就不是这一层的了
2.不能某个祖先的dis大于k,就直接break了。因为到分治树祖先的距离没有单调性!!!!
代码:
#include<bits/stdc++.h> #define il inline #define reg register int #define numb (ch^'0') #define mid ((l+r)>>1) using namespace std; typedef long long ll; il void rd(int &x){char ch;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x); } namespace Miracle{ const int N=100000+5; int n,m; struct node{int nxt,to; }e[2*N]; int hd[N],cnt; void add(int x,int y){e[++cnt].nxt=hd[x];e[cnt].to=y;hd[x]=cnt; } int fa[N]; int sz[N]; int mx[N]; int nowsz; int tmprt; int rt[N][2];//0 is myself ; 1 is disfather int nowrt; struct tr{int ls,rs;int sum; }t[N*50]; int tot; int dist[N][20]; int dep[N]; int val[N]; int vis[N]; void pushup(int x){t[x].sum=t[t[x].ls].sum+t[t[x].rs].sum; } void upda(int &x,int l,int r,int p,int v){if(!x) x=++tot;if(l==r){t[x].sum+=v;return;}if(p<=mid) upda(t[x].ls,l,mid,p,v);else upda(t[x].rs,mid+1,r,p,v);pushup(x); } int query(int x,int l,int r,int L,int R){//no dis=0 (myself)if(L>R) return 0;if(L<=l&&r<=R){return t[x].sum;}int ret=0;if(L<=mid) ret+=query(t[x].ls,l,mid,L,R);if(mid<R) ret+=query(t[x].rs,mid+1,r,L,R);return ret; } void dfs1(int x,int f,int d,int dis){//find nowrtsz[x]=1;mx[x]=0;dep[x]=d;if(d!=1){upda(tmprt,0,n,dis,val[x]);}for(reg i=hd[x];i;i=e[i].nxt){int y=e[i].to;if(vis[y]||y==f) continue;dfs1(y,x,d,dis+1);sz[x]+=sz[y];mx[x]=max(mx[x],sz[y]);}mx[x]=max(mx[x],nowsz-sz[x]);if(mx[x]<=nowsz/2&&(nowsz-sz[x])<=nowsz/2){nowrt=x;} } void dfs2(int x,int f,int d,int dis){//find dis from nowrtsz[x]=1;dep[x]=d;dist[x][d]=dis;upda(rt[nowrt][0],0,n,dis,val[x]);for(reg i=hd[x];i;i=e[i].nxt){int y=e[i].to;if(vis[y]||y==f) continue;dfs2(y,x,d,dis+1);sz[x]+=sz[y];} } void divi(int x,int d,int f){//mxsz=0; // cout<<" x "<<x<<" : "<<d<<" "<<f<<endl;nowrt=0;tmprt=0;dfs1(x,0,d,1);fa[nowrt]=f;rt[nowrt][1]=tmprt; // cout<<" nowrt "<<nowrt<<endl;dfs2(nowrt,0,d,0);vis[nowrt]=1;int tmp=nowrt;for(reg i=hd[tmp];i;i=e[i].nxt){int y=e[i].to;if(!vis[y]){nowsz=sz[y];divi(y,d+1,tmp);}} } int wrk0(int x,int k){int ret=0;ret+=query(rt[x][0],0,n,0,k);int tmp=x;while(fa[x]){int y=fa[x];// if(k-dist[tmp][dep[y]]>=0) ret+=query(rt[y][0],0,n,0,k-dist[tmp][dep[y]]);// else break;ret-=query(rt[x][1],0,n,0,k-dist[tmp][dep[y]]);x=y;}return ret; } void wrk1(int x,int v){int tmp=x;int c=v-val[x];val[x]=v;upda(rt[x][0],0,n,0,c);while(fa[x]){int y=fa[x];upda(rt[x][1],0,n,dist[tmp][dep[y]],c);upda(rt[y][0],0,n,dist[tmp][dep[y]],c);x=y;} } int main(){rd(n);rd(m);for(reg i=1;i<=n;++i) rd(val[i]);int x,y;for(reg i=1;i<n;++i){rd(x);rd(y);add(x,y);add(y,x);}nowsz=n;divi(1,1,0); // cout<<" toot "<<tot<<endl;int op,k;int lasans=0;while(m--){rd(op);rd(x);rd(k);x^=lasans;k^=lasans;if(op==0) printf("%d\n",lasans=wrk0(x,k));else wrk1(x,k);}return 0; }} signed main(){ // freopen("data.in","r",stdin); // freopen("my.out","w",stdout); Miracle::main();return 0; }/*Author: *Miracle*Date: 2019/2/6 10:11:29 */
总结:
动态点分治往往为了去重,经常考虑x对fa的贡献
相当于在分治树的往fa走的边上造了一个线段树
(每个点一个,每个边一个,一共n+n-1个)
转载于:https://www.cnblogs.com/Miracevin/p/10353703.html
bzoj3730. 震波相关推荐
- BZOJ3730 震波 【动态点分治】*
BZOJ3730 震波 Description 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土 ...
- [BZOJ3730]震波(动态点分治)
3730: 震波 Time Limit: 15 Sec Memory Limit: 256 MB Submit: 2260 Solved: 470 [Submit][Status][Discuss ...
- BZOJ3730 震波+BZOJ4372 烁烁的游戏(动态点分治)
震波 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的 ...
- [BZOJ3730]震波-动态点分治
震波 Description 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土地常常发生地震,并 ...
- Bzoj3730 震波
Time Limit: 15 Sec Memory Limit: 256 MB Submit: 753 Solved: 176 Description 在一片土地上有N个城市,通过N-1条无向边互 ...
- Bzoj3730: 震波
题面 戳我 Sol 动态点分治: 建个点分树,每个节点开两颗线段树,以与该点的距离为下标,维护价值和 一棵树维护这个点的,一棵维护对上层重心的贡献 然后.. 然后?直接暴力搞就行了 注意常数优化我TL ...
- bzoj3730震波
这是一道动态点分治好题. 在点分树上,对于每个点,维护两个树状数组,一个维护离点分中心距离不超过某个值的点权和,另一个维护离点分中心的父亲距离不超过某个值的点权和.注意树状数组的大小不必开到联通子树的 ...
- [BZOJ3730]震波
题目 点这里看题目. BZOJ 目测-是炸了. 分析 动态点分治入门题. 首先理解什么叫 " 动态点分治 ". 一般点分治需要离线解决,不带修改.动态点分治可 ...
- BZOJ3730 震波 【动态点分治】
传送门 SOL 点分树模板 细节看注释吧 多写几遍应该就好了 CODE #include<bits/stdc++.h> using namespace std; #define sf sc ...
最新文章
- 深度包检测 DPI 介绍
- 利用logistic回归构建申请信用评级案例
- cview类 public_在MFC单文档的View类中,如何获得指向状态栏的指针
- P3708-koishi的数学题【差分】
- 算法竞赛入门经典 例题6-2 铁轨(C、python)
- 计算机科学的知识领域
- 通用的《求职信》范文模板
- 配置微软Azure Kinect DK 录制器k4arecorder
- 详解Django的CSRF认证
- 在html中 标题单元格的标记是,html表格标题标签是什么
- Work around for SQL Configuration Manager Consol
- python 矩阵求转置、行列式、迹、求逆
- 笔记本亮度无法调节的可能原因
- 【考试记录】阿里云DevOps助理工程师(ACA)
- matlab在命令行注册,在命令行窗口中输入语句
- git revert回退时提示One or more files are in a conflicted state
- java byte与char互转原理_java byte与char互转原理
- 电感与磁珠(补充中)
- 大型互联网系统架构演进之路
- ios微信软键盘之殇