LOJ 6145 Easy (动态点分治+线段树)
先建出来点分树,以每个点为根开线段树,维护点分子树内编号为$[l,r]$的儿子到根的距离最小值
每次查询$x$开始,沿着点分树向上跑,在每个点的线段树的$[l,r]$区间里都查一遍取$min$即可
因为题目让我们求最小值,所以出现重复经过同一条路径的情况并不会让答案变坏
如果让我们求最大值呢?似乎可以用主席树搞搞?(仅仅是口胡有空再想)
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 100005
#define M1 505
#define ll long long
#define uint unsigned int
#define ush unsigned short
using namespace std;
const int inf=0x3f3f3f3f; template <typename _T> void read(_T &ret)
{
ret=; _T fh=; char c=getchar();
while(c<''||c>''){ if(c=='-') fh=-; c=getchar(); }
while(c>=''&&c<=''){ ret=ret*+c-''; c=getchar(); }
ret=ret*fh;
} struct Edge{
int to[N1*],nxt[N1*],val[N1*],head[N1],cte;
void ae(int u,int v,int w)
{ cte++; to[cte]=v; nxt[cte]=head[u]; val[cte]=w; head[u]=cte; }
}e; int lg[N1*],de;
namespace Tree{
int dis[N1],dep[N1],fa[N1],st[N1],ff[N1*][],cur; //ord[N1*2],
void dfs1(int x)
{
int j,v; st[x]=++cur; ff[cur][]=x;
for(j=e.head[x];j;j=e.nxt[j])
{
v=e.to[j]; if(v==fa[x]) continue;
fa[v]=x; dis[v]=dis[x]+e.val[j]; dep[v]=dep[x]+;
dfs1(v); ff[++cur][]=x;
}
}
void init()
{
dep[]=; dfs1();
int i,j;
for(i=,lg[]=;i<=cur;i++) lg[i]=lg[i>>]+;
for(j=;j<=lg[cur];j++)
for(i=;i+(<<j)-<=cur;i++)
ff[i][j]=dep[ff[i][j-]] < dep[ff[i+(<<(j-))][j-]] ? ff[i][j-] : ff[i+(<<(j-))][j-];
}
inline int Dis(int x,int y)
{
int i=st[x],j=st[y],F; if(i>j) swap(i,j);
F=dep[ff[i][lg[j-i+]]] < dep[ff[j-(<<lg[j-i+])+][lg[j-i+]]] ? ff[i][lg[j-i+]] : ff[j-(<<lg[j-i+])+][lg[j-i+]];
return dis[x]+dis[y]-*dis[F];
}
}; struct SEG{
struct node{ int ls,rs,mi; };
node a[N1*]; int root[N1],tot;
inline void pushup(int rt)
{
a[rt].mi=inf;
if(a[rt].ls) a[rt].mi=min(a[rt].mi,a[a[rt].ls].mi);
if(a[rt].rs) a[rt].mi=min(a[rt].mi,a[a[rt].rs].mi);
}
void upd(int x,int l,int r,int &rt,int w)
{
if(!rt) rt=++tot;
if(l==r){ a[rt].mi=w; return; }
int mid=(l+r)>>;
if(x<=mid) upd(x,l,mid,a[rt].ls,w);
else upd(x,mid+,r,a[rt].rs,w);
pushup(rt);
}
int qmi(int L,int R,int l,int r,int rt)
{
if(!rt) return inf;
if(L<=l&&r<=R) return a[rt].mi;
int mid=(l+r)>>; int ans=inf;
if(L<=mid) ans=min(ans,qmi(L,R,l,mid,a[rt].ls));
if(R>mid) ans=min(ans,qmi(L,R,mid+,r,a[rt].rs));
return ans;
}
}s; using Tree::Dis; int n;
int sz[N1],ms[N1],use[N1],pfa[N1],SZ,G; void gra(int x,int dad,int now)
{
int j,v; sz[x]=; ms[x]=;
if(now) s.upd(x,,n,s.root[now],Dis(x,now));
for(j=e.head[x];j;j=e.nxt[j])
{
v=e.to[j]; if(v==dad || use[v]) continue;
gra(v,x,now);
sz[x]+=sz[v]; ms[x]=max(ms[x],sz[v]);
}
ms[x]=max(ms[x],SZ-sz[x]);
if(ms[x]<ms[G]) G=x;
} void main_dfs(int x)
{
int j,v; use[x]=;
s.upd(x,,n,s.root[x],);
for(j=e.head[x];j;j=e.nxt[j])
{
v=e.to[j]; if(use[v]) continue;
SZ=sz[v]; G=; gra(v,x,x); pfa[G]=x;
main_dfs(G);
}
} int main()
{
scanf("%d",&n);
int i,j,x,y,w,Q,q,l,r,D,ans;
for(i=;i<n;i++)
{
read(x), read(y), read(w);
e.ae(x,y,w); e.ae(y,x,w);
}
Tree::init();
ms[]=n; SZ=n; gra(,,); main_dfs(G);
scanf("%d",&Q);
for(q=;q<=Q;q++)
{
read(l), read(r), read(x); ans=inf;
for(y=x;y;y=pfa[y])
{
D=Dis(x,y);
ans=min(ans,D+s.qmi(l,r,,n,s.root[y]));
}
printf("%d\r\n",ans);
}
return ;
}
LOJ 6145 Easy (动态点分治+线段树)的更多相关文章
- 【loj6145】「2017 山东三轮集训 Day7」Easy 动态点分治+线段树
题目描述 给你一棵 $n$ 个点的树,边有边权.$m$ 次询问,每次给出 $l$ .$r$ .$x$ ,求 $\text{Min}_{i=l}^r\text{dis}(i,x)$ . $n,m\le ...
- 【bzoj4372】烁烁的游戏 动态点分治+线段树
题目描述 给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:Q x:询问x的点权.M x d w:将树上与节点x距离不超过d的节点的点权均加上w. 输入 第一行两个正整数:n,m接下来的n-1 ...
- 【bzoj3730】震波 动态点分治+线段树
题目描述 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时代的发展,城市 ...
- BZOJ4372烁烁的游戏——动态点分治+线段树(点分树套线段树)
题目描述 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠.题意:给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠.烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠.皮皮鼠会被 ...
- [bzoj4372] 烁烁的游戏 [动态点分治+线段树+容斥原理]
题面 传送门 思路 观察一下题目,要求的是修改"距离点$u$的距离一定的点权值",那这个就不能用传统的dfs序类算法+线段树维护,因为涉及到向父亲回溯的问题 看到和树上距离相关的东 ...
- 2019ICPC上海网络赛 A Lightning Routing I 点分树(动态点分治)+线段树
题意 给一颗带边权的树,有两种操作 \(C~e_i~w_i\),将第\(e_i\)条边的边权改为\(w_i\). \(Q~v_i\),询问距\(v_i\)点最远的点的距离. 分析 官方题解做法:动态维 ...
- BZOJ 4372/3370 烁烁的游戏/震波 (动态点分治+线段树)
烁烁的游戏 题目大意: 给你一棵$n$个节点的树,有$m$次操作,询问某个节点的权值,或者将与某个点$x$距离不超过$d$的所有节点的权值都增加$w$ 动态点分裸题 每个节点开一棵权值线段树 对于修改 ...
- BZOJ3730震波——动态点分治+线段树(点分树套线段树)
题目描述 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时代的发展,城市 ...
- BZOJ4372 烁烁的游戏(动态点分治+线段树)
建出点分树,每个节点维护其作为点分树上lca对子树内点的贡献,线段树维护即可,同时另开一个线段树以减掉父亲重复的贡献. #include<iostream> #include<cst ...
随机推荐
- 云上kafka和自建kafka对比
说起Kafka,许多使用者对它是又爱又恨.Kafka是一种分布式的.基于发布/订阅的消息系统,其极致体验让人欲罢不能,但操心的运维.复杂的安全策略.可靠性易用性的缺失.算不上极致的性能发挥.并不丰富的 ...
- Hackerrank Connected Cell in a Grid
Problem Statement You are given a matrix with m rows and n columns of cells, each of which contains ...
- 三种常见的编码:ASCII码、UTF-8编码、Unicode编码等字符占领的字节数
ASCII码: 一个英文字母(不分大写和小写)占一个字节的空间.一个中文汉字占两个字节的空间. 一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制. 最小值0,最大值25 ...
- js实现伪音乐盒
支持快进 <div class="music-part"> <div class="box-bg"></div> <d ...
- luogu2744 量取牛奶
题目大意 给出一个整数集合$A$,总数$N$,规定一个整数序列$\{a_n\}, \forall i, a_i\in A$满足条件:存在一个正整数序列$\{k_n\}$,使得$\sum_{i=1}^n ...
- Android 体系结构介绍
转自:http://blog.sina.com.cn/s/blog_4bc996c40100fawo.html 第一.操作系统层(OS)第二.各种库(Libraries)和Android 运行环境(R ...
- 洛谷 P1083 [ NOIP 2012 ] 借教室 —— 线段树 / 二分差分数组
题目:https://www.luogu.org/problemnew/show/P1083 当初不会线段树的时候做这道题...对差分什么不太熟练,一直没A,放在那儿不管... 现在去看,线段树就直接 ...
- bzoj3505 [Cqoi2014]数三角形——组合数+容斥
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3505 好题啊好题...好像还曾经出现在什么智力测试卷中来着...当时不会现在还是无法自己推出 ...
- php验证邮箱是否合法
下面我来总结了在php邮箱验证的正则表达式以及还可以checkdnsrr函数来验证你输入的邮箱是否是有效的哦,这样可以更好的过滤到无效邮箱地址哦. 域名由各国文字的特定字符集.英文字母.数字及 ...
- poj1200Crazy Search(hash)
题目大意 将一个字符串分成长度为N的字串.且不同的字符不会超过NC个.问总共有多少个不同的子串. /* 字符串hash O(n)枚举起点 然后O(1)查询子串hash值 然后O(n)找不一样的个数 ...