【bzoj4372】烁烁的游戏
Description
给一颗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节点的皮皮鼠数量。
Solution
遇到深度,那么就要想树分治。
考虑重心之间容斥解决。
维护两颗线段树分别表示点分树某重心子树内到它的距离等于d的点和子树内到他父亲距离等于d的点
然后查询的时候跳点分树fa,和之前的点容斥后统计答案即可。
Code
#include<bits/stdc++.h>
#define ls sn[id][0]
#define rs sn[id][1]
using namespace std;
struct edge{int y,nxt;
}e[400010];
int n,m,tot,cnt,rt,ss;
int f[100010];
int sz[100010];
int fa[100010];
int siz[100010];
int top[100010];
int dep[100010];
int son[100010];
int rt1[100010];
int rt2[100010];
int head[100010];
int maxn[100010];
int tree[100010<<8];
int sn[100010<<8][2];
bool vis[100010];
void add(int x,int y){tot++;e[tot].y=y;e[tot].nxt=head[x];head[x]=tot;
}
void dfs1(int x){sz[x]=1;for(int i=head[x];i;i=e[i].nxt){int y=e[i].y;if(fa[x]==y) continue;dep[y]=dep[x]+1;fa[y]=x;dfs1(y);sz[x]+=sz[y];if(sz[y]>sz[son[x]]) son[x]=y;}
}
void dfs2(int x,int tp){top[x]=tp;if(son[x]) dfs2(son[x],tp);for(int i=head[x];i;i=e[i].nxt)if(e[i].y!=son[x]&&e[i].y!=fa[x])dfs2(e[i].y,e[i].y);
}
int lca(int x,int y){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);x=fa[top[x]];}if(dep[x]>dep[y]) swap(x,y);return x;
}
int dis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];
}
void getroot(int x,int fa){siz[x]=1;maxn[x]=0;for(int i=head[x];i;i=e[i].nxt) {int y=e[i].y;if(y==fa||vis[y]) continue;getroot(y,x);siz[x]+=siz[y];maxn[x]=max(maxn[x],siz[y]);}maxn[x]=max(maxn[x],ss-siz[x]);if(maxn[x]<maxn[rt]) rt=x;
}
void solve(int x,int fa){f[x]=fa;vis[x]=true;for(int i=head[x];i;i=e[i].nxt){int y=e[i].y;if(vis[y]) continue;rt=0,ss=siz[y],getroot(y,0);solve(rt,x);}
}
void change(int &id,int l,int r,int ul,int ur,int v){if(!id) id=++cnt;if(ul<=l&&ur>=r){tree[id]+=v;return;}int mid=(l+r)>>1;if(ul<=mid) change(ls,l,mid,ul,ur,v);if(ur>mid) change(rs,mid+1,r,ul,ur,v);
}
int query(int id,int l,int r,int x){if(!id) return 0;if(l==r) return tree[id];int mid=(l+r)>>1;if(x<=mid) return tree[id]+query(ls,l,mid,x);else return tree[id]+query(rs,mid+1,r,x);
}
void update(int x,int d,int v){change(rt1[x],0,n,0,d,v);for(int i=x;f[i];i=f[i]){int s=dis(x,f[i]);if(s>d) continue;change(rt1[f[i]],0,n,0,d-s,v);change(rt2[i],0,n,0,d-s,v);}
}
int qry(int x){int res=query(rt1[x],0,n,0);for(int i=x;f[i];i=f[i]) {int s=dis(x,f[i]);res+=query(rt1[f[i]],0,n,s)-query(rt2[i],0,n,s);}return res;
}
int read(){char ch=getchar();int x=0;while(ch>'9'||ch<'0') ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();return x;
}
int main(){int x,y,z;char op[10];n=read(),m=read();for(int i=1;i<n;i++){x=read(),y=read();add(x,y),add(y,x);}dfs1(1);dfs2(1,1);maxn[0]=ss=n;getroot(1,0),solve(rt,0);for(int i=1;i<=m;i++){scanf("%s",op);if(op[0]=='M'){x=read(),y=read(),z=read();update(x,y,z);}else{x=read();printf("%d\n",qry(x));}}
}
【bzoj4372】烁烁的游戏相关推荐
- [bzoj4372]烁烁的游戏
[bzoj4372]烁烁的游戏 动态点分,需要注意的是我们对于每个点要开两个数组,另外一个相当于一个容斥,即把他父亲上的减掉. 代码 #include<bits/stdc++.h> usi ...
- BZOJ4372: 烁烁的游戏
BZOJ4372: 烁烁的游戏 https://lydsy.com/JudgeOnline/problem.php?id=4372 分析: 不是很难想的一道题,用树状数组维护点分树上每一层分治中心的点 ...
- [BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA]
[BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA] 题目大意: 给定一颗nn个节点的树,边权均为11,初始每个点权值为00 . 其中操作QQ xx询问x点的点权,操作 MM xx dd ...
- BZOJ3730 震波+BZOJ4372 烁烁的游戏(动态点分治)
震波 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的 ...
- BZOJ4372: 烁烁的游戏【动态点分治】
Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w ...
- BZOJ4372 烁烁的游戏(动态点分治+线段树)
建出点分树,每个节点维护其作为点分树上lca对子树内点的贡献,线段树维护即可,同时另开一个线段树以减掉父亲重复的贡献. #include<iostream> #include<cst ...
- bzoj4372. 烁烁的游戏【动态点分治】
传送门 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗nnn个节点的树,边权均为111,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点uuu,把周围与他距离不超过d的节点各吸引出www ...
- BZOJ4372: 烁烁的游戏(动态点分治)
Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w ...
- bzoj4372 烁烁的游戏 动态点分治+线段树
Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠 ...
- bzoj4372 烁烁的游戏
题目描述 题解: 动态 点分治. 点分治可以帮助我们将树上的点分层,如果我们把这些点按生成顺序建树的话,我们会得到一棵点分树. 点分树有一个特别好的性质,就是不管原来的树长什么样,建出来的点分树的深度 ...
最新文章
- FDMemTable 数据集
- 大型项目开发,你准备好了吗?
- IDEA 快捷键 Android Studio快捷键
- golang grpc demo
- 玩转oracle 11g(40):Oracle11g 不区分大小写设定
- JAVA 堆栈 堆 方法区 解析
- mysql 时间段内的周末_淘宝用户行为数据分析(MySQL)
- 《无线网络技术教程第二版》阅读笔记(一)
- 使用路由器配置DHCP
- HDU1325 Is It A Tree?
- js使用的一些实用技巧
- 修炼Python基础篇-字典(Dictionary)学习
- A870省电内核超频内核介绍及下载[七夕]
- 凡诺cms2.1文件包含漏洞分析
- 微信小程序:UI好看的王者荣耀战力查询助手小程序源码
- luoguP4313 文理分科
- 互联网日报 | 阿里拟280亿港元控股高鑫零售;小米首发80瓦无线秒充;国产特斯拉整车出口海外...
- JS 中 0/1 与 true/false 是否相等
- 火狐浏览器如何设置默认打开网页
- 分析一个有特色的实用资源无忧鸟网址导航大全