烁烁的游戏

Description

背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠。
题意:
给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠。
烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠。皮皮鼠会被烁烁吸引,所以会一直待在节点上不动。
烁烁很好奇,在当前时刻,节点u有多少个他的好朋友—皮皮鼠。
大意:
给一颗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节点的皮皮鼠数量。

解法:

先考虑暴力。对于每一次查询,把整棵树遍历一遍,对于每个遍历到的节点,加上当前节点到查询点的距离的所有的修改值。最后得到的就是这个点的点权。
有了思路,就上树分治啦!每个点开2棵可区间修改的李超线段树。
第一棵线段树: 以子树中的每一个点到自己的距离为下标,维护每一种距离的修改值。
第二棵线段树: 以子树中的每一个点到自己的父亲的距离为下标,维护每一种距离的修改值。
修改: 设要修改的点为u,要与u距离不超过d1的所有点加上w。在向上爬的过程中,设当前爬到节点为i,u到fa[i]的距离为d2。则将fa[i]的第一棵线段树下标为0 ~ d1-d2都加上w,再将用于去掉重复的i的第二棵线段树下标为0 ~ d1-d2都加上w。
查询: 其实统计答案的原理和暴力是一样的。在向上爬的过程中,设当前点的父亲到查询点的距离为d。对于每个祖先节点,答案加上这个点的父亲的第一棵线段树下标为d的修改值,再减去这个点的第二棵线段树下标为d的修改值,目的仍然是减去重复的。
代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100005;
int n,m,u,v,d,cnt,head[N],to[N*2],nxt[N*2];
int idx,lg2[N*2],dfn[N],dep[N],siz[N],pos[N*2],f[N*2][20];
int mi,size,rt,fa[N];
int tot,root[N][2],tag[20000005],ch[20000005][2];
bool vis[N];
char s[5];
void adde(int u,int v){to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
}
void dfs(int pre,int u){dfn[u]=++idx;pos[idx]=u;int v;for(int i=head[u];i;i=nxt[i]){v=to[i];if(v!=pre){dep[v]=dep[u]+1;dfs(u,v);pos[++idx]=u;}}
}
void st(){for(int i=1;i<=idx;i++){f[i][0]=pos[i];}for(int j=1;j<=20;j++){for(int i=1;i+(1<<j)-1<=idx;i++){if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]){f[i][j]=f[i][j-1];}else{f[i][j]=f[i+(1<<(j-1))][j-1];}}}
}
int lca(int u,int v){if(dfn[u]>dfn[v]){swap(u,v);}int k=lg2[dfn[v]-dfn[u]];if(dep[f[dfn[u]][k]]<dep[f[dfn[v]-(1<<k)+1][k]]){return f[dfn[u]][k];}else{return f[dfn[v]-(1<<k)+1][k];}
}
void dfsroot(int pre,int u){siz[u]=1;int v,mx=0;for(int i=head[u];i;i=nxt[i]){v=to[i];if(v!=pre&&!vis[v]){dfsroot(u,v);siz[u]+=siz[v];mx=max(mx,siz[v]);}}mx=max(mx,size-siz[u]);if(mx<mi){mi=mx;rt=u;}
}
int dis(int u,int v){return dep[u]+dep[v]-2*dep[lca(u,v)];
}
void build(int pre,int u){vis[u]=true;fa[u]=pre;int v;for(int i=head[u];i;i=nxt[i]){v=to[i];if(!vis[v]){mi=size=siz[v];dfsroot(u,v);build(u,rt);}}
}
void upd(int &o,int l,int r,int L,int R,int v){if(!o){o=++tot;}if(L==l&&R==r){tag[o]+=v;return;}int mid=(l+r)/2;if(R<=mid){upd(ch[o][0],l,mid,L,R,v);}else if(L>mid){upd(ch[o][1],mid+1,r,L,R,v);}else{upd(ch[o][0],l,mid,L,mid,v);upd(ch[o][1],mid+1,r,mid+1,R,v);}
}
int qry(int o,int l,int r,int k){if(!o){return 0;}if(l==r){return tag[o];}int mid=(l+r)/2;if(k<=mid){return tag[o]+qry(ch[o][0],l,mid,k);}{return tag[o]+qry(ch[o][1],mid+1,r,k);}
}
int query(int u){int ret=qry(root[u][0],0,n,0),tmp;for(int i=u;fa[i];i=fa[i]){tmp=dis(fa[i],u);ret+=qry(root[fa[i]][0],0,n,tmp)-qry(root[i][1],0,n,tmp);}return ret;
}
void update(int u,int d,int w){upd(root[u][0],0,n,0,d,w);int tmp;for(int i=u;fa[i];i=fa[i]){tmp=dis(fa[i],u);if(tmp>d){continue;}upd(root[fa[i]][0],0,n,0,d-tmp,w);upd(root[i][1],0,n,0,d-tmp,w);}
}
int main(){for(int i=2;i<=200000;i++){lg2[i]=lg2[i/2]+1;}scanf("%d%d",&n,&m);for(int i=1;i<n;i++){scanf("%d%d",&u,&v);adde(u,v);adde(v,u);}dfs(0,1);st();mi=size=n;dfsroot(0,1);build(0,rt);for(int i=1;i<=m;i++){scanf("%s%d",s,&u);if(s[0]=='Q'){printf("%d\n",query(u));              }else{scanf("%d%d",&d,&v);update(u,d,v);                                             }}return 0;
}

【bzoj4372】 烁烁的游戏【动态树分治】相关推荐

  1. [BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA]

    [BZOJ4372][烁烁的游戏][动态树分治+线段树+LCA] 题目大意: 给定一颗nn个节点的树,边权均为11,初始每个点权值为00 . 其中操作QQ xx询问x点的点权,操作 MM xx dd ...

  2. 【BZOJ4372】烁烁的游戏 动态树分治+线段树

    [BZOJ4372]烁烁的游戏 Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳到一个节点u,把周围 ...

  3. bzoj4372 烁烁的游戏 动态点分治+线段树

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

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

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

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

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

  6. bzoj 4372: 烁烁的游戏 动态点分治_树链剖分_线段树

    [Submit][Status][Discuss] Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠. 题意: 给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠. 烁烁他每次会跳 ...

  7. bzoj 4372 烁烁的游戏 —— 动态点分治+树状数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 本以为和 bzoj3730 一样,可以直接双倍经验了: 但要注意一下,树状数组不能查询 ...

  8. bzoj 4372 烁烁的游戏——动态点分治+树状数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 和 bzoj 3070 震波 是一个套路.注意区间修改的话,树状数组不能表示 dis ...

  9. 【BZOJ3924】[Zjoi2015]幻想乡战略游戏 动态树分治

    [BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网 ...

  10. [bzoj4372]烁烁的游戏

    [bzoj4372]烁烁的游戏 动态点分,需要注意的是我们对于每个点要开两个数组,另外一个相当于一个容斥,即把他父亲上的减掉. 代码 #include<bits/stdc++.h> usi ...

最新文章

  1. pthread_cond_wait()加一个while为什么的解释
  2. js解决iframe跨域问题
  3. 牛人总结python中string模块各属性以及函数的用法,果断转了,好东西
  4. 工业局的云计算机,广州市海珠区科技工业商务和信息化局方奕涛局长带队二次调研云算...
  5. numpy基础(part14)--积分
  6. 前端学习(3002):vue+element今日头条管理--模块介绍
  7. c语言指针访问 静态变量_使用C中的指针访问变量的值
  8. Java面试之JVM参数调优
  9. Mysql 5.7 Gtid内部学习(十) 实际案例(二)
  10. L2-013. 红色警报
  11. mellanox驱动安装
  12. C Primer Plus 第四章 复习题编程练习 答案
  13. 三、Win10 64位PyCharm下打包.py程序为可执行exe文件且兼容32位和64位
  14. android 投屏 版本号,Android开源投屏软件——Scrcpy
  15. 合理设置 让你的迅雷下载速度越来越快
  16. 这三个步骤让你知道WPS如何转换成WORD文档
  17. 计划任务linux每天执行一次,linux 每天执行任务计划
  18. 』 [大话IT]我编的计算机基础教材,大家批判批判
  19. matlab取点坐标之前先将图片放大缩小
  20. 使用Spring实现读写分离(MySQL实现主从复制)

热门文章

  1. 【架构风格】架构风格演进和领域架构分类
  2. HTML5 canvas 行星环绕
  3. 软件工程作业--网上书店
  4. Git 工作常用命令行
  5. DICTATOR第一周二分查找作业
  6. 阿里云搭建自己的anki服务器
  7. 数据结构与算法之线性表(超详细顺序表、链表)
  8. 压缩机的 压缩比、内容积比、内压力比概念你不要搞混淆了
  9. **Django介绍 和 MVT 模式 MVC 模式对比**
  10. 30 张图带你了解 CPU 制作全过程