【BZOJ4372】烁烁的游戏

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节点的皮皮鼠数量。

Sample Input

7 6
1 2
1 4
1 5
2 3
2 7
5 6
M 1 1 2
Q 5
M 2 2 3
Q 3
M 1 2 1
Q 2

Sample Output

2
3
6

HINT

数据范围:
n,m<=10^5,|w|<=10^4
注意:w不一定为正整数,因为烁烁可能把皮皮鼠吓傻了。

题解:动态点分治+线段树裸题,每个节点开两棵线段树维护它子树中的以及它的父亲要从它中减去的即可。

注意特判边界的问题。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=100010;
int n,m,tot,ans,cnt,mn,rt;
struct sag
{int ls,rs,sum;
}s[maxn*150];
int to[maxn<<1],next[maxn<<1],head[maxn],siz[maxn],dep[maxn],pos[maxn],md[20][maxn<<1],fa[maxn],Log[maxn<<1];
int r1[maxn],r2[maxn];
bool vis[maxn];
char str[5];
inline void add(int a,int b)
{to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void getrt(int x,int fa)
{int i,tmp=0;siz[x]=1;for(i=head[x];i!=-1;i=next[i])   if(!vis[to[i]]&&to[i]!=fa) getrt(to[i],x),siz[x]+=siz[to[i]],tmp=max(tmp,siz[to[i]]);tmp=max(tmp,tot-siz[x]);if(tmp<mn) mn=tmp,rt=x;
}
void solve(int x)
{vis[x]=1;for(int i=head[x];i!=-1;i=next[i])    if(!vis[to[i]])tot=siz[to[i]],mn=1<<30,getrt(to[i],x),fa[rt]=x,solve(rt);
}
void dfs(int x,int fa)
{md[0][++pos[0]]=dep[x],pos[x]=pos[0];for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa)dep[to[i]]=dep[x]+1,dfs(to[i],x),md[0][++pos[0]]=dep[x];
}
inline int getmin(int a,int b)
{a=pos[a],b=pos[b];if(a>b) swap(a,b);int k=Log[b-a+1];return min(md[k][a],md[k][b-(1<<k)+1]);
}
inline int dis(int a,int b)
{return dep[a]+dep[b]-2*getmin(a,b);
}
void updata(int l,int r,int &x,int a,int b)
{if(a<0) return ;if(!x)  x=++tot;s[x].sum+=b;if(l==r) return ;int mid=(l+r)>>1;if(a<=mid) updata(l,mid,s[x].ls,a,b);else  updata(mid+1,r,s[x].rs,a,b);
}
int query(int l,int r,int x,int a,int b)
{if(!x||(a<=l&&r<=b))   return s[x].sum;int mid=(l+r)>>1;if(b<=mid) return  query(l,mid,s[x].ls,a,b);if(a>mid)   return  query(mid+1,r,s[x].rs,a,b);return query(l,mid,s[x].ls,a,b)+query(mid+1,r,s[x].rs,a,b);
}
inline int rd()
{int ret=0,f=1;   char gc=getchar();while(gc<'0'||gc>'9')  {if(gc=='-')    f=-f;  gc=getchar();}while(gc>='0'&&gc<='9')  ret=ret*10+(gc^'0'),gc=getchar();return ret*f;
}
int main()
{n=rd(),m=rd();int i,j,x,y,a,b,u;memset(head,-1,sizeof(head));for(i=1;i<n;i++)  a=rd(),b=rd(),add(a,b),add(b,a);dfs(1,0),tot=n,mn=1<<30,getrt(1,0),solve(rt),tot=0;for(j=1;(1<<j)<=2*n-1;j++)   for(i=1;i+(1<<j)-1<=2*n-1;i++)    md[j][i]=min(md[j-1][i],md[j-1][i+(1<<(j-1))]);for(i=2;i<=2*n-1;i++) Log[i]=Log[i>>1]+1;for(i=1;i<=m;i++){scanf("%s",str);if(str[0]=='Q'){u=rd(),ans=0;for(x=u;x;x=y){y=fa[x];ans+=query(0,n,r1[x],dis(u,x),n);if(y) ans-=query(0,n,r2[x],dis(u,y),n);}printf("%d\n",ans);}else{u=rd(),a=rd(),b=rd();for(x=u;x;x=y){y=fa[x];updata(0,n,r1[x],min(n,a-dis(u,x)),b);if(y) updata(0,n,r2[x],min(n,a-dis(u,y)),b);}}}return 0;
}//7 2 1 2 1 4 1 5 2 3 2 7 5 6 M 1 2 1 Q 2

转载于:https://www.cnblogs.com/CQzhangyu/p/7965538.html

【BZOJ4372】烁烁的游戏 动态树分治+线段树相关推荐

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

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

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

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

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

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

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

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

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

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

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

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

  7. 震波——动态点分治+线段树

    题目 [题目描述] 在一片土地上有 $N$ 个城市,通过 $N-1$ 条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为 $1$,其中第 $i$ 个城市的价值为 $value[i]$. 不幸的是 ...

  8. BZOJ 3730: 震波 动态树分治 线段树 lca

    3730: 震波 Time Limit: 15 Sec  Memory Limit: 256 MB Submit: 1202  Solved: 288 [Submit][Status][Discuss ...

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

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

最新文章

  1. 【机器学习】谷歌的速成课程(二)
  2. PyTorch基础(三)-----神经网络包nn和优化器optim
  3. linux accept 队列,[译] TCP的SYN队列和Accept队列
  4. centos 查找nginx_centos7肿么查看已经安装nginx
  5. [渝粤教育] 西南科技大学 经济数学1 在线考试复习资料
  6. 为什么长视频没有强算法推荐的产品
  7. mybatis源码分析、底层原理
  8. [BZOJ1998][Hnoi2010]Fsk物品调度
  9. 让 ASP.NET AJAX 支持浏览器的 History Navigation - Part 1
  10. windows 快捷方式(.lnk)代码执行漏洞(CVE-2017-8464 )[附EXP生成工具]
  11. Android学习JNI,使用C调用JAVA语言
  12. graphviz安装
  13. 简述java重载和重写的相同点_方法的重载和重写的异同之处
  14. 财务分析中三张财务报表计算公式
  15. Linux 上格式化ssd硬盘方法
  16. c语言求布尔矩阵的乘积,离散数学 关系矩阵的布尔乘法的简便方法
  17. 4行代码实现微信送祝福,这个新年有点不一样
  18. 红色的反色是青色引申出PS怎么反色之教程
  19. 五面拿下阿里飞猪offer,java发送notes邮件
  20. 学习社会工程学需要什么前置知识

热门文章

  1. 浅谈NLM非局部均值滤波
  2. step7设置pcpg_怎么安装STEP7编程软件及PG/PC接口设置
  3. cairo之安装配置
  4. python-机器学习-决策树实现
  5. RS232实现串口双向通讯
  6. LinuxC中“库函数”的使用和常用的“输出函数”。
  7. 异常点检测isolationforest
  8. tableau ODBC驱动下载方法和链接(连接mysql的驱动)
  9. 如何快速更改电脑ip地址【图文教程】?
  10. 拉基米德米表系统源码含简易后台