题面戳我

题意:

给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:

Q x:询问x的点权。

M x d w:将树上与节点x距离不超过d的节点的点权均加上w。

\(1≤n≤10^5\)

sol

和前一题是一样的[BZOJ3730]震波

这里是线段树的区间修改+单点查询。标记永久化就很舒服(不用pushup和pushdown)

code

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100005;
int gi()
{
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
struct edge{int to,next;}a[N<<1];
int n,m,head[N],cnt,pa[N],dep[N],sz[N],son[N],top[N];
int root,sum,w[N],vis[N],fa[N],rt[N<<1],tot;
struct segment_tree{int ls,rs,v;}t[N*300];
void dfs1(int u,int f)
{
pa[u]=f;dep[u]=dep[f]+1;sz[u]=1;
for (int e=head[u];e;e=a[e].next)
{
int v=a[e].to;if (v==f) continue;
dfs1(v,u);
sz[u]+=sz[v];if (sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int up)
{
top[u]=up;
if (son[u]) dfs2(son[u],up);
for (int e=head[u];e;e=a[e].next)
if (a[e].to!=pa[u]&&a[e].to!=son[u])
dfs2(a[e].to,a[e].to);
}
int lca(int u,int v)
{
while (top[u]^top[v])
{
if (dep[top[u]]<dep[top[v]]) swap(u,v);
u=pa[top[u]];
}
return dep[u]<dep[v]?u:v;
}
int getdis(int u,int v){return dep[u]+dep[v]-(dep[lca(u,v)]<<1);}
void getroot(int u,int f)
{
sz[u]=1;w[u]=0;
for (int e=head[u];e;e=a[e].next)
{
int v=a[e].to;if (v==f||vis[v]) continue;
getroot(v,u);
sz[u]+=sz[v];w[u]=max(w[u],sz[v]);
}
w[u]=max(w[u],sum-sz[u]);
if (w[u]<w[root]) root=u;
}
void solve(int u,int f)
{
fa[u]=f;vis[u]=1;int pre_sum=sum;
for (int e=head[u];e;e=a[e].next)
{
int v=a[e].to;if (vis[v]) continue;
if (sz[v]>sz[u]) sum=pre_sum-sz[u];
else sum=sz[v];
root=0;
getroot(v,0);
solve(root,u);
}
}
void Modify(int &x,int l,int r,int ql,int qr,int v)
{
if (!x) x=++tot;
if (l>=ql&&r<=qr) {t[x].v+=v;return;}
int mid=l+r>>1;
if (ql<=mid) Modify(t[x].ls,l,mid,ql,qr,v);
if (qr>mid) Modify(t[x].rs,mid+1,r,ql,qr,v);
}
int Query(int x,int l,int r,int pos)
{
if (!x) return 0;
if (l==r) return t[x].v;
int mid=l+r>>1;
if (pos<=mid) return t[x].v+Query(t[x].ls,l,mid,pos);
else return t[x].v+Query(t[x].rs,mid+1,r,pos);
}
void PreModify()
{
int u=gi(),d=gi(),v=gi();
Modify(rt[u],0,n-1,0,d,v);
for (int i=u;fa[i];i=fa[i])
{
int dist=getdis(u,fa[i]);
if (d>=dist) Modify(rt[fa[i]],0,n-1,0,d-dist,v),Modify(rt[i+n],0,n-1,0,d-dist,v);
}
}
int PreQuery()
{
int u=gi(),res=Query(rt[u],0,n-1,0);
for (int i=u;fa[i];i=fa[i])
{
int dist=getdis(u,fa[i]);
res+=Query(rt[fa[i]],0,n-1,dist)-Query(rt[i+n],0,n-1,dist);
}
return res;
}
int main()
{
n=gi();m=gi();
for (int i=1;i<n;i++)
{
int u=gi(),v=gi();
a[++cnt]=(edge){v,head[u]};head[u]=cnt;
a[++cnt]=(edge){u,head[v]};head[v]=cnt;
}
dfs1(1,0);dfs2(1,1);
sum=w[0]=n;
getroot(1,0);
solve(root,0);
while (m--)
{
char ch=getchar();
while (ch!='Q'&&ch!='M') ch=getchar();
if (ch=='Q') printf("%d\n",PreQuery());
else PreModify();
}
return 0;
}

[BZOJ4372]烁烁的游戏的更多相关文章

  1. BZOJ3730 震波 和 BZOJ4372 烁烁的游戏

    "震波"题意 F.A.Qs Home Discuss ProblemSet Status Ranklist Contest 入门OJ ModifyUser  autoint Log ...

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

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

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

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

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

    和[BZOJ3730]震波几乎一样,每个点建两棵线段树分别代表它的管辖范围内以它为LCA的路径的贡献和它对父亲的贡献. 注意点分树上的点的距离在原树上不单调,所以不能有若距离超出限制就break之类的 ...

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

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

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

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

  7. [bzoj4372] 烁烁的游戏 [动态点分治+线段树+容斥原理]

    题面 传送门 思路 观察一下题目,要求的是修改"距离点$u$的距离一定的点权值",那这个就不能用传统的dfs序类算法+线段树维护,因为涉及到向父亲回溯的问题 看到和树上距离相关的东 ...

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

    [BZOJ4372]烁烁的游戏(动态点分治) 题面 BZOJ 大意: 每次在一棵书上进行操作 1.将离某个点u的距离不超过d的点的权值加上w 2.询问单点权值 题解 这题和前面那一道震波几乎是一模一样 ...

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

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

随机推荐

  1. DataGrid 拖动 附加属性类

    项目需要实现一个DataGrid拖动排序,于是参考网上一些资源然后,修改了下实现了一个附加属性类,如下 使用方法 <DataGrid x:Name="shareGrid" t ...

  2. 携程Apollo(阿波罗)配置中心在.NET Core项目快速集成

    .NET Core的支持文档大体上可以参考文档.Net客户端使用指南:https://github.com/ctripcorp/apollo/wiki/.Net%E5%AE%A2%E6%88%B7%E ...

  3. 打通MySQL的操作权限

    打通MySQL的操作权限 前面已经总结了<XAMPP的配置与使用>,虽然可以直接通过GUI控制面板去启动MySQL服务,但是有些相关的操作则需要在Windows中的CMD命令窗口中去对My ...

  4. PyCharm安装及使用

    搭建环境 1.win10_X64,其他Win版本也可以. 2.PyCharm版本:Professional-2016.2.3. 搭建准备 1.到PyCharm官网下载PyCharm安装包.   Dow ...

  5. NFS工作原理

    很多同学都知道NFS的使用场景,也知道如何配置和使用,但对NFS的工作原理了解的很少. NFS是C/S模式,首先要有一台服务端跑NFS服务,然后各个客户端直接挂载共享目录使用.NFS服务本身不会监听端 ...

  6. 一步一步从原理跟我学邮件收取及发送 13.mime格式与常见字符编码

    在前面的本系列文章中我们已经学会了邮件的发送和收取.但在收取中我们看到的是一串串的乱码,回忆前面的发送过程,我们会奇怪:我们前面的邮件是明文啊.为什么明文的邮件明明也可以正常工作,还要弄乱码似的字符串 ...

  7. 蚂蚁爬杆问题 UVA 10881

    算法入门经典训练指南上的题. 这里有必要讲一下蚂蚁爬杆问题:每只蚂蚁都有一个初始方向,相撞会转向,关键就是相撞的处理,由于速度并不会改变,两只蚂蚁相撞,可以看做,两只蚂蚁穿过对方,继续沿原方向前进,经 ...

  8. 分享一个Appium/selenium测试报告模板

    介绍 这个模板改编自 这位外国老哥 效果图 错误截图 录像 失败的case可以点击"view"查看报错信息, 也可以点击screenshot查看截图信息,更可以点击replay查看 ...

  9. python更新数据库脚本两种方法

    最近项目的两次版本迭代中,根据业务需求的变化,需要对数据库进行更新,两次分别使用了不同的方式进行更新. 第一种:使用python的MySQLdb模块利用原生的sql语句进行更新 import MySQ ...

  10. Wireshark抓包常见出现错误

    转自这里 1.   tcp out-of-order(tcp有问题) 解答: 1).    应该有很多原因.但是多半是网络拥塞,导致顺序包抵达时间不同,延时太长,或者包丢失,需要重新组合数据单元 因为 ...