loj

description

一棵树,每次给出\(l,r,x\),求从点\(x\)出发到达\([l,r]\)中任意一点的最短距离。

sol

动态点分治。

建出点分树后,在每个节点上用以点编号为下标的线段树维护出子树中所有点到他的距离。

对于一组询问只要暴跳父亲然后查询就可以了。

一般而言写动态点分治的时候要维护两个东西,一个是当前节点子树的信息,另一个是当前子树给上一级重心(也就是点分树上的父亲的所有贡献)方便在计算时减去。但是在这里,因为题目中要求的是\(min\),而重复计算不会影响结果的正确性(因为距离只可能算大不可能算小),所以只维护一棵线段树就行了。

时间复杂度\(O(n\log^2n)\),注意空间复杂度也是\(O(n\log^2n)\)。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
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;
}
const int N = 2e5+5;
int n,q,to[N],nxt[N],ww[N],head[N],cnt,dfn[N],tim,dep[N],st[20][N],lg[N];
int sz[N],w[N],sum,root,vis[N],fa[N],rt[N],tot;
struct seg{int ls,rs,mn;}t[N*150];
void link(int u,int v,int w){
to[++cnt]=v;nxt[cnt]=head[u];ww[cnt]=w;head[u]=cnt;
}
void dfs(int u,int f){
st[0][dfn[u]=++tim]=dep[u];
for (int e=head[u];e;e=nxt[e])
if (to[e]!=f){
dep[to[e]]=dep[u]+ww[e];dfs(to[e],u);
st[0][++tim]=dep[u];
}
}
int dis(int u,int v){
int res=dep[u]+dep[v];u=dfn[u],v=dfn[v];
if (u>v) swap(u,v);int k=lg[v-u+1];
res-=min(st[k][u],st[k][v-(1<<k)+1])<<1;
return res;
}
void getroot(int u,int f){
sz[u]=1;w[u]=0;
for (int e=head[u];e;e=nxt[e])
if (to[e]!=f&&!vis[to[e]]){
getroot(to[e],u);
sz[u]+=sz[to[e]];
w[u]=max(w[u],sz[to[e]]);
}
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;
for (int e=head[u];e;e=nxt[e])
if (!vis[to[e]]){
sum=sz[to[e]];root=0;
getroot(to[e],0);solve(root,u);
}
}
void modify(int &x,int l,int r,int p,int v){
if (!x) x=++tot,t[x].mn=1e9;t[x].mn=min(t[x].mn,v);
if (l==r) return;int mid=l+r>>1;
if (p<=mid) modify(t[x].ls,l,mid,p,v);
else modify(t[x].rs,mid+1,r,p,v);
}
int query(int x,int l,int r,int ql,int qr){
if (!x) return (int)1e9;
if (l>=ql&&r<=qr) return t[x].mn;
int mid=l+r>>1;
if (qr<=mid) return query(t[x].ls,l,mid,ql,qr);
if (ql>mid) return query(t[x].rs,mid+1,r,ql,qr);
return min(query(t[x].ls,l,mid,ql,qr),query(t[x].rs,mid+1,r,ql,qr));
}
int main(){
n=gi();
for (int i=1;i<n;++i){
int u=gi(),v=gi(),w=gi();
link(u,v,w);link(v,u,w);
}
dfs(1,0);
for (int i=2;i<=tim;++i) lg[i]=lg[i>>1]+1;
for (int j=1;j<=lg[tim];++j)
for (int i=1;i+(1<<j)-1<=tim;++i)
st[j][i]=min(st[j-1][i],st[j-1][i+(1<<j-1)]);
w[0]=sum=n;getroot(1,0);solve(root,0);
for (int i=1;i<=n;++i)
for (int u=i;u;u=fa[u])
modify(rt[u],1,n,i,dis(u,i));
q=gi();while (q--){
int l=gi(),r=gi(),u=gi(),x=u,ans=1e9;
while (x) ans=min(ans,query(rt[x],1,n,l,r)+dis(x,u)),x=fa[x];
printf("%d\n",ans);
}
return 0;
}

[LOJ6145][2017 山东三轮集训 Day7]Easy的更多相关文章

  1. 「2017 山东三轮集训 Day7 解题报告

    「2017 山东三轮集训 Day7」Easy 练习一下动态点分 每个点开一个线段树维护子树到它的距离 然后随便查询一下就可以了 注意线段树开大点... Code: #include <cstdi ...

  2. 【loj6145】「2017 山东三轮集训 Day7」Easy 动态点分治+线段树

    题目描述 给你一棵 $n$ 个点的树,边有边权.$m$ 次询问,每次给出 $l$ .$r$ .$x$ ,求 $\text{Min}_{i=l}^r\text{dis}(i,x)$ . $n,m\le ...

  3. 「2017 山东三轮集训 Day7」Easy

    一棵带边权的树,多次询问 $x$ 到编号为 $[l,r]$ 的点最短距离是多少 $n \leq 100000$ sol: 动态点分治,每层重心维护到所有点的距离 查询的时候在管辖这个点的 log 层线 ...

  4. #6145. 「2017 山东三轮集训 Day7」Easy 动态点分治

    \(\color{#0066ff}{题目描述}\) JOHNKRAM 最近在参加 C_SUNSHINE 举办的聚会. C 国一共有 n 座城市,这些城市由 n−1 条无向道路连接.任意两座城市之间有且 ...

  5. LOJ #6145. 「2017 山东三轮集训 Day7」Easy 点分树+线段树

    这个就比较简单了~ Code: #include <cstdio> #include <algorithm> #define N 100004 #define inf 1000 ...

  6. 「2017 山东三轮集训 Day1」Flair

    模拟赛的题 好神仙啊 题面在这里 之前的Solution很蠢 现在已经update.... 题意 有$ n$个商品价格均为$ 1$,您有$ m$种面值的货币,面值为$ C_1..C_m$ 每种物品你有 ...

  7. 【loj6142】「2017 山东三轮集训 Day6」A 结论题+Lucas定理

    题解: 当奇数 发现答案就是C(n,1)^2+C(n,3)^2+...C(n,n)^2 倒序相加,发现就是C(2n,n) 所以答案就是C(2n,n)/2 当偶数 好像并不会证 打表出来可以得到 2.当 ...

  8. loj #6138. 「2017 山东三轮集训 Day4」Right

    题目: 题解: 暴力一波 \(SG\) 函数可以发现这么一个规律: \(p\) 为奇数的时候 : \(SG(n) = n \% 2\) \(p\) 为偶数的时候 : \(SG(n) = n \% (p ...

  9. loj #6136. 「2017 山东三轮集训 Day4」Left

    题目: 题解: 我们可以发现所有的交换器都是一个位置连接着下一层左侧的排序网络,另一个位置连着另一侧的排序网络. 而下一层是由两个更低阶的排序网络构成的. 两个网络互不干扰.所以我们可以通过第一行和最 ...

随机推荐

  1. NSMutableString和NSString区别,及相互转换方法

    NSString是一个不可变的字符串对象.这不是表示这个对象声明的变量的值不可变,而是表示它初始化以后,你不能改变该变量所分配的内存中的值,但你可以重新分配该变量所处的内存空间.而NSMutableS ...

  2. 【转】TCP那些事(上,下)

    TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较痛苦的过程,但对于学习的过程却能让人有很多收获.关于TCP这个协议的细节,我还是推荐你去 ...

  3. js今日小结—Ajax、前端安全、GET&POST、闭包、HTTPS

    HTTPS HTTP+加密(SSL.TLS)+认证+完整性保护 = HTTPS: GET和POST的区别 get拉取数据,post传输数据 get请求能被浏览器主动缓存,post不会(除非手动) ge ...

  4. C++(二十九) — new 和 delete

    1.基本用法,定义变量.数组.对象 class test { public: test(int a_, int b_) { a = a_; b = b_; cout << "构造 ...

  5. C语言实现顺序表

    C语言实现顺序表代码 文件SeqList.cpp #pragma warning(disable: 4715) #include"SeqList.h" void ShowSeqLi ...

  6. dom&bom的起源,方法,内容,应用

    Document Object Model的历史可以追溯至1990年代后期微软与Netscape的"浏览器大战"(browser wars),双方为了在JavaScript与JSc ...

  7. day5-re模块

    一.概述 但凡有过语言开发经验的童鞋都清楚,很多时候需要进行字符串的匹配搜索.查找替换等处理,此时正则表达式就是解决问题的不二法门.正则表达式并不是Python的一部分.正则表达式是用于处理字符串的强 ...

  8. 华为EPON OLT开局配置

      配置思路: 1. 登录olt(console进去之后配地址) 2.配置上联口(配vlan和起三层地址互联路由的lan口) 3.epon接分光器,分光器下接光猫 4.自动发现光猫.配置DBA数据和线 ...

  9. Quartz教程一:使用quartz

    原文链接 | 译文链接 | 翻译:nkcoder | 校对:方腾飞 本系列教程由quartz-2.2.x官方文档翻译.整理而来,希望给同样对quartz感兴趣的朋友一些参考和帮助,有任何不当或错误之处 ...

  10. js Worker 线程

    在平时的运行的javascript脚本都在主线程中执行,如果当前脚本包含复杂的.耗时的代码.那么JavaScript脚本的执行将会被阻塞,甚至整个刘看齐都是提示失去响应. 例子: 假设程序需要计算.收 ...