bzoj4372 烁烁的游戏
题目描述
题解:
动态 点分治。
点分治可以帮助我们将树上的点分层,如果我们把这些点按生成顺序建树的话,我们会得到一棵点分树。
点分树有一个特别好的性质,就是不管原来的树长什么样,建出来的点分树的深度都大约是$logn$。
而且若在点分树中a有一个儿子b,那么在原树中a的管辖子树(即找a作重心的子树)一定包含b的管辖子树。
(管辖子树这个名词是我瞎编的)
相当于把树分块,点分树中每一个点代表一块,
这样就是……树上线段树……了?
好像这就是动态点分。
本题要求区间修改,单点查询。
区间一个一个修改是不可能的,这辈子都不可能的
一定有骚操作,比如说挂几个标记。
比如每个点挂一棵线段树,然后记录管辖子树中和这个点距离为k的有多大收益。
比如这个图。
红点是高级重心,橙点是低级重心。
我们会发现,橙点能力过强时,他可以将部分范围传给高级中心。
但是有重叠部分啊。
所以我们还需要再开一棵线段树。
由于一个低级中心在点分树中只能有一个高级中心做父亲,所以我们可以在低级中心记录溢出了多少。
这道题就愉快的结束了。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 100050 inline int rd() {int f=1,c=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}return f*c; } int n,m,hed[N],cnt; char c; struct EG {int to,nxt; }e[2*N]; void ae(int f,int t) {e[++cnt].to = t;e[cnt].nxt = hed[f];hed[f] = cnt; } int fa[N],son[N],dep[N],siz[N],top[N]; void dfs1(int u,int f) {fa[u] = f;siz[u] = 1;dep[u] = dep[f]+1;for(int j=hed[u];j;j=e[j].nxt){int to = e[j].to;if(to==f)continue;dfs1(to,u);siz[u]+=siz[to];if(siz[to]>siz[son[u]])son[u] = to;} } void dfs2(int u,int tp) {top[u] = tp;if(!son[u])return ;dfs2(son[u],tp);for(int j=hed[u];j;j=e[j].nxt){int to = e[j].to;if(to!=fa[u]&&to!=son[u])dfs2(to,to);} } int get_lca(int x,int y) {while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);x = fa[top[x]];}return dep[x]<dep[y]?x:y; } int get_dis(int x,int y) {return dep[x]+dep[y]-2*dep[get_lca(x,y)]; } int rt,mrk[N],uf[N],sum,w[N],sz[N]; void get_rt(int u,int f) {sz[u] = 1,w[u] = 0;for(int j=hed[u];j;j=e[j].nxt){int to = e[j].to;if(to==f||mrk[to])continue;get_rt(to,u);sz[u]+=sz[to];if(sz[to]>w[u])w[u]=sz[to];}w[u] = max(w[u],sum - sz[u]);if(w[u]<w[rt])rt = u; } void work(int u) {mrk[u] = 1;int pre = sum;for(int j=hed[u];j;j=e[j].nxt){int to = e[j].to;if(mrk[to])continue;rt = 0,sum = (sz[to]>sz[u]?pre-sz[u]:sz[to]);get_rt(to,0);uf[rt] = u;work(rt);} } struct segtree {int tot,rt[N],ls[150*N],rs[150*N],vl[150*N];void insert(int l,int r,int &u,int qx,int d){if(!u)u = ++tot;vl[u]+=d;if(l==r)return ;int mid = (l+r)>>1;if(qx<=mid)insert(l,mid,ls[u],qx,d);else insert(mid+1,r,rs[u],qx,d);}int query(int l,int r,int u,int ql,int qr){if(!u)return 0;if(l==ql&&r==qr)return vl[u];int mid = (l+r)>>1;if(qr<=mid)return query(l,mid,ls[u],ql,qr);else if(ql>mid)return query(mid+1,r,rs[u],ql,qr);else return query(l,mid,ls[u],ql,mid)+query(mid+1,r,rs[u],mid+1,qr); }void push(int x,int s,int d){s = min(s,n);insert(0,n,rt[x],s,d);}int ask(int x,int s){return query(0,n,rt[x],s,n);} }tr1,tr2; int main() { // freopen("1.in","r",stdin);n = rd(),m = rd();for(int f,t,i=1;i<n;i++){f = rd(),t = rd();ae(f,t),ae(t,f);}dfs1(1,0),dfs2(1,1);w[0] = 0x3f3f3f3f,rt = 0,sum = n;get_rt(1,0);work(rt);for(int x,d,w,i=1;i<=m;i++){c = getchar();while(c!='Q'&&c!='M')c = getchar();if(c=='Q'){x = rd();int ans = 0,p=x;while(p){ans+=tr1.ask(p,get_dis(p,x));if(uf[p])ans-=tr2.ask(p,get_dis(uf[p],x));p = uf[p];}printf("%d\n",ans);}else{x = rd(),d = rd(),w = rd();int p = x,las = 0;while(p){int now = d-get_dis(p,x);if(now<0){las = p,p = uf[p];continue;}tr1.push(p,now,w);if(las)tr2.push(las,now,w);las = p,p = uf[p];}}}return 0; }
转载于:https://www.cnblogs.com/LiGuanlin1124/p/10190471.html
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只皮皮鼠 ...
最新文章
- [英文面試]如何寫面試後的感謝信
- 百度bae mysql_微信公众号开发第二课 百度BAE搭建和数据库使用
- Omi应用md2site发布-markdown转网站利器
- APDPlat的系统启动和关闭流程剖析
- java注解编程_java 注解 基本原理 编程实现
- java与c应用,Java和C应用程序之间的IPC
- myabatis oracle 调用存储过程返回list结果集
- 使用numpy.tanh()打印矢量/矩阵元素的双曲正切值 使用Python的线性代数
- ROS on ARM--RK3066上本地编译ROS Groovy
- 负载均衡技术沙龙2期圆满结束(现场图文、PPT)
- 用ajax实现图片上传 帮你简单快速学会使用
- 网页游戏外挂的设计与编写:QQ摩天大楼【二】(登陆准备-信息处理方式)
- 木讷的程序员需要知道的事情 (六)
- linux shell中环境变量$PS1详解
- AE插件:能量激光描边光效特效Saber Mac
- JDBC连接Mysql并统计指定关键词在某一列中出现的次数
- 灰度巡线传感器_探索者D1系列教程十 巡线传感器
- c语言json 5c,什么是json的转义字符
- 使用Pelican在Github(国外线路访问)和Coding(国内线路访问)同步托管博客
- ConvNeXt网络详解