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】烁烁的游戏相关推荐

  1. [bzoj4372]烁烁的游戏

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

  2. BZOJ4372: 烁烁的游戏

    BZOJ4372: 烁烁的游戏 https://lydsy.com/JudgeOnline/problem.php?id=4372 分析: 不是很难想的一道题,用树状数组维护点分树上每一层分治中心的点 ...

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

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

  4. BZOJ3730 震波+BZOJ4372 烁烁的游戏(动态点分治)

    震波 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的 ...

  5. BZOJ4372: 烁烁的游戏【动态点分治】

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

  6. BZOJ4372 烁烁的游戏(动态点分治+线段树)

    建出点分树,每个节点维护其作为点分树上lca对子树内点的贡献,线段树维护即可,同时另开一个线段树以减掉父亲重复的贡献. #include<iostream> #include<cst ...

  7. bzoj4372. 烁烁的游戏【动态点分治】

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

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

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

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

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

  10. bzoj4372 烁烁的游戏

    题目描述 题解: 动态 点分治. 点分治可以帮助我们将树上的点分层,如果我们把这些点按生成顺序建树的话,我们会得到一棵点分树. 点分树有一个特别好的性质,就是不管原来的树长什么样,建出来的点分树的深度 ...

最新文章

  1. FDMemTable 数据集
  2. 大型项目开发,你准备好了吗?
  3. IDEA 快捷键 Android Studio快捷键
  4. golang grpc demo
  5. 玩转oracle 11g(40):Oracle11g 不区分大小写设定
  6. JAVA 堆栈 堆 方法区 解析
  7. mysql 时间段内的周末_淘宝用户行为数据分析(MySQL)
  8. 《无线网络技术教程第二版》阅读笔记(一)
  9. 使用路由器配置DHCP
  10. HDU1325 Is It A Tree?
  11. js使用的一些实用技巧
  12. 修炼Python基础篇-字典(Dictionary)学习
  13. A870省电内核超频内核介绍及下载[七夕]
  14. 凡诺cms2.1文件包含漏洞分析
  15. 微信小程序:UI好看的王者荣耀战力查询助手小程序源码
  16. luoguP4313 文理分科
  17. 互联网日报 | 阿里拟280亿港元控股高鑫零售;小米首发80瓦无线秒充;国产特斯拉整车出口海外...
  18. JS 中 0/1 与 true/false 是否相等
  19. 火狐浏览器如何设置默认打开网页
  20. 分析一个有特色的实用资源无忧鸟网址导航大全

热门文章

  1. 知识图谱入门学习笔记(一)-概念
  2. STM32F407ZGT6之硬件介绍
  3. 文献【综述】Hallmarks of Cancer: The Next Generation 肿瘤的新十大特征
  4. 基于脱敏数据,使用huggingface的Transformers预训练模型
  5. 【情报工具】分享15款保护隐私的搜索引擎
  6. 【从零开始】阿里云服务器配置web开发环境及部署本地web项目
  7. 组态王与三菱PLC编程软件GXWorks2通过OPC数据库进行动态仿真
  8. 组合导航+多传感器融合算法
  9. 咸鱼ESP32实例—MQTT
  10. vue 图片,视频点击预览按钮方法