bzoj 4372: 烁烁的游戏 动态点分治_树链剖分_线段树
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节点的皮皮鼠数量。
和震波拿到题十分相似,具体做法参考一下震波
Code:
#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 6011111
#define N 500010
#define inf 0x7f7f7f
using namespace std;
int hd[N],nx[N],to[N],cnt;
int n,m,val[N],vis[N];
void add(int u,int v)
{
nx[++cnt]=hd[u],hd[u]=cnt,to[cnt]=v;
}
namespace heavyedge{
int dep[N],hson[N],fa[N],siz[N],top[N];
void dfs1(int u,int ff)
{
dep[u]=dep[ff]+1,fa[u]=ff,siz[u]=1;
for(int i=hd[u];i;i=nx[i])
if(to[i]!=ff)
{
dfs1(to[i],u),siz[u]+=siz[to[i]];
if(siz[to[i]]>siz[hson[u]]) hson[u]=to[i];
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
if(hson[u]) dfs2(hson[u],tp);
for(int i=hd[u];i;i=nx[i])
{
if(to[i]==fa[u]||to[i]==hson[u]) continue;
dfs2(to[i],to[i]);
}
}
int LCA(int u,int v)
{
while(top[u]!=top[v]) dep[top[u]] < dep[top[v]] ? v = fa[top[v]] : u = fa[top[u]];
return dep[u] < dep[v] ? u : v;
}
int main()
{
dfs1(1,0), dfs2(1,1);
return 0;
}
};
int Dis(int u,int v)
{
return heavyedge::dep[u] + heavyedge::dep[v] - (heavyedge::dep[heavyedge::LCA(u,v)] << 1);
}
int siz[N],f[N],root,sn,Fa[N];
int GetRoot(int u,int ff)
{
siz[u] = 1,f[u] = 0;
for(int i = hd[u]; i ; i = nx[i])
{
if(to[i] == ff || vis[to[i]]) continue;
GetRoot(to[i],u);
siz[u] += siz[to[i]];
f[u] = max(f[u],siz[to[i]]);
} f[u] = max(f[u],sn - siz[u]);
if(f[u] < f[root]) root = u;
}
void dfs(int u)
{
vis[u] = 1;
for(int i = hd[u]; i ; i = nx[i])
{
if(vis[to[i]]) continue;
root = 0, sn = siz[to[i]], GetRoot(to[i],u);
Fa[root] = u, dfs(root);
}
}
struct Segment_Tree{
#define ls (t[o].l)
#define rs (t[o].r)
int tot;
struct Node
{
int l,r,v;
}t[maxn<<1];
void update(int &o,int l,int r,int p,int w)
{
if(!o) o = ++cnt;
t[o].v += w;
if(l == r) return;
int mid = (l + r) >> 1;
if(p <= mid) update(t[o].l,l,mid,p,w);
else update(t[o].r,mid + 1,r,p,w);
} int query(int o,int l,int r,int L,int R)
{
if(!o || l > r) return 0;
if(l >= L && r <= R) return t[o].v;
int mid = (l + r) >> 1,res = 0;
if(L <= mid) res += query(t[o].l,l,mid,L,R);
if(R >= mid + 1) res += query(t[o].r,mid + 1,r, L,R);
return res;
}
}T;
int ans = 0,rt[N];
#define fax(x) (x + n)
void Update(int x,int k,int w)
{
T.update(rt[x],0,n,0,w),T.update(rt[x],0,n,k + 1,-w);
for(int i = x; Fa[i]; i = Fa[i])
{
int dis = Dis(x, Fa[i]);
if(k - dis < 0) continue;
T.update(rt[Fa[i]],0,n,0,w),T.update(rt[Fa[i]],0,n,k - dis + 1,-w);
T.update(rt[fax(i)],0,n,0,w),T.update(rt[fax(i)],0,n,k - dis + 1,-w);
}
}
int Query(int x)
{
int res = T.query(rt[x],0,n,0,0);
for(int i = x; Fa[i] ; i = Fa[i])
{
int dis = Dis(x, Fa[i]);
res += T.query(rt[Fa[i]],0,n,0,dis);
res -= T.query(rt[fax(i)],0,n,0,dis);
}
return res;
}
char str[20];
int main()
{
// setIO("input");
scanf("%d%d",&n,&m);
for(int i = 1,u,v;i < n; ++i) scanf("%d%d",&u,&v), add(u,v),add(v,u);
heavyedge :: main();
f[0] = inf, sn = n,root = 0,GetRoot(1,0), dfs(root);
while(m--)
{
int x,y,z;
scanf("%s",str);
if(str[0] == 'M') scanf("%d%d%d",&x,&y,&z),Update(x,y,z);
if(str[0] == 'Q') scanf("%d",&x), printf("%d\n",Query(x));
}
return 0;
}
bzoj 4372: 烁烁的游戏 动态点分治_树链剖分_线段树的更多相关文章
- bzoj 4372 烁烁的游戏——动态点分治+树状数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 和 bzoj 3070 震波 是一个套路.注意区间修改的话,树状数组不能表示 dis ...
- bzoj 4372 烁烁的游戏 —— 动态点分治+树状数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 本以为和 bzoj3730 一样,可以直接双倍经验了: 但要注意一下,树状数组不能查询 ...
- BZOJ.4515.[SDOI2016]游戏(树链剖分 李超线段树)
BZOJ 洛谷 每次在路径上加的数是个一次函数,容易看出是树剖+李超线段树维护函数最小值.所以其实依旧是模板题. 横坐标自然是取个确定的距离标准.取每个点到根节点的距离\(dis[i]\)作为\(i\ ...
- BZOJ 2402 陶陶的难题II (树链剖分、线段树、凸包、分数规划)
毒瘤,毒瘤,毒瘤-- \(30000\)这个数据范围,看上去就是要搞事的啊... 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2402 ...
- BZOJ 4732 UOJ #268 [清华集训2016]数据交互 (树链剖分、线段树)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...
- 数据结构(树链剖分,线段树):SDOI 2016 游戏
4515: [Sdoi2016]游戏 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 351 Solved: 157[Submit][Status][ ...
- [bzoj4515][Sdoi2016]游戏-树链剖分+李超线段树
Brief Description Alice 和 Bob 在玩一个游戏. 游戏在一棵有 n 个点的树上进行.最初,每个点上都只有一个数字,那个数字是 123456789123456789. 有时,A ...
- bzoj 1576 [Usaco2009 Jan]安全路经Travel(树链剖分,线段树)
[题意] 给定一个无向图,找到1-i所有的次短路经,要求与最短路径的最后一条边不重叠. [思路] 首先用dijkstra算法构造以1为根的最短路树. 将一条无向边看作两条有向边,考察一条不在最短路树上 ...
- bzoj 4034 [HAOI2015] T2(树链剖分,线段树)
4034: [HAOI2015]T2 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1536 Solved: 508[Submit][Status] ...
随机推荐
- Python 实现 Excel 里单元格的读写与清空操作
#coding=utf-8 # coding=utf-8 作用是声明python代码的文本格式是utf-8,python按照utf-8的方式来读取程序. # 如果不加这个声明,无论代码中还是注释中有中 ...
- 学习EXTJS6(2)“Hello Usegear”
由于零基础,extjs6的资料不够多,所以直接动手困难不少.<Extjs Web应用程序开发指南>机械出版社虽然有点老,但是用于学习一步一步动手实践还是相当不错的.用的是extjs4.0. ...
- hdu 1384 查分约束
#include<stdio.h> /* 要善于挖掘隐含条件 dis[v]-dis[u]>=bian[i].w;一个条件(u,v,bian[i].w); dis[i+1]>=d ...
- Tkinter之Label
最近要弄弄以前想弄的东东了, 所以图形界面不可少,,TKinter, 就用它了, 简单,满足要求. #coding: utf8 from Tkinter import * def tklabel(ev ...
- [Javascript Crocks] Apply a function in a Maybe context to Maybe inputs (curry & ap & liftA2)
Functions are first class in JavaScript. This means we can treat a function like any other data. Thi ...
- Kinect for Windows SDK v2.0 开发笔记 (十五) 手势帧
(转载请注明出处) 使用SDK: Kinect for Windows SDK v2.0 public preview1409 同前面,由于SDK未完毕,不附上函数/方法/接口的超链接. 这次最 ...
- 深度学习实战篇-基于RNN的中文分词探索
深度学习实战篇-基于RNN的中文分词探索 近年来,深度学习在人工智能的多个领域取得了显著成绩.微软使用的152层深度神经网络在ImageNet的比赛上斩获多项第一,同时在图像识别中超过了人类的识别水平 ...
- Eddy's picture
Eddy's picture Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Tota ...
- 如何让音频跟视频在ios跟android上自动播放
如何让音频跟视频在ios跟android上自动播放 <audio autoplay ><source src="audio/alarm1.mp3" type=&q ...
- 【BZOJ2438】【中山市选2011】杀人游戏
[问题描述] 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面, 查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, ...