loj

description

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

sol

动态点分治。

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

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

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

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

code

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. using namespace std;
  5. int gi(){
  6. int x=0,w=1;char ch=getchar();
  7. while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
  8. if (ch=='-') w=0,ch=getchar();
  9. while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
  10. return w?x:-x;
  11. }
  12. const int N = 2e5+5;
  13. int n,q,to[N],nxt[N],ww[N],head[N],cnt,dfn[N],tim,dep[N],st[20][N],lg[N];
  14. int sz[N],w[N],sum,root,vis[N],fa[N],rt[N],tot;
  15. struct seg{int ls,rs,mn;}t[N*150];
  16. void link(int u,int v,int w){
  17. to[++cnt]=v;nxt[cnt]=head[u];ww[cnt]=w;head[u]=cnt;
  18. }
  19. void dfs(int u,int f){
  20. st[0][dfn[u]=++tim]=dep[u];
  21. for (int e=head[u];e;e=nxt[e])
  22. if (to[e]!=f){
  23. dep[to[e]]=dep[u]+ww[e];dfs(to[e],u);
  24. st[0][++tim]=dep[u];
  25. }
  26. }
  27. int dis(int u,int v){
  28. int res=dep[u]+dep[v];u=dfn[u],v=dfn[v];
  29. if (u>v) swap(u,v);int k=lg[v-u+1];
  30. res-=min(st[k][u],st[k][v-(1<<k)+1])<<1;
  31. return res;
  32. }
  33. void getroot(int u,int f){
  34. sz[u]=1;w[u]=0;
  35. for (int e=head[u];e;e=nxt[e])
  36. if (to[e]!=f&&!vis[to[e]]){
  37. getroot(to[e],u);
  38. sz[u]+=sz[to[e]];
  39. w[u]=max(w[u],sz[to[e]]);
  40. }
  41. w[u]=max(w[u],sum-sz[u]);
  42. if (w[u]<w[root]) root=u;
  43. }
  44. void solve(int u,int f){
  45. fa[u]=f;vis[u]=1;
  46. for (int e=head[u];e;e=nxt[e])
  47. if (!vis[to[e]]){
  48. sum=sz[to[e]];root=0;
  49. getroot(to[e],0);solve(root,u);
  50. }
  51. }
  52. void modify(int &x,int l,int r,int p,int v){
  53. if (!x) x=++tot,t[x].mn=1e9;t[x].mn=min(t[x].mn,v);
  54. if (l==r) return;int mid=l+r>>1;
  55. if (p<=mid) modify(t[x].ls,l,mid,p,v);
  56. else modify(t[x].rs,mid+1,r,p,v);
  57. }
  58. int query(int x,int l,int r,int ql,int qr){
  59. if (!x) return (int)1e9;
  60. if (l>=ql&&r<=qr) return t[x].mn;
  61. int mid=l+r>>1;
  62. if (qr<=mid) return query(t[x].ls,l,mid,ql,qr);
  63. if (ql>mid) return query(t[x].rs,mid+1,r,ql,qr);
  64. return min(query(t[x].ls,l,mid,ql,qr),query(t[x].rs,mid+1,r,ql,qr));
  65. }
  66. int main(){
  67. n=gi();
  68. for (int i=1;i<n;++i){
  69. int u=gi(),v=gi(),w=gi();
  70. link(u,v,w);link(v,u,w);
  71. }
  72. dfs(1,0);
  73. for (int i=2;i<=tim;++i) lg[i]=lg[i>>1]+1;
  74. for (int j=1;j<=lg[tim];++j)
  75. for (int i=1;i+(1<<j)-1<=tim;++i)
  76. st[j][i]=min(st[j-1][i],st[j-1][i+(1<<j-1)]);
  77. w[0]=sum=n;getroot(1,0);solve(root,0);
  78. for (int i=1;i<=n;++i)
  79. for (int u=i;u;u=fa[u])
  80. modify(rt[u],1,n,i,dis(u,i));
  81. q=gi();while (q--){
  82. int l=gi(),r=gi(),u=gi(),x=u,ans=1e9;
  83. while (x) ans=min(ans,query(rt[x],1,n,l,r)+dis(x,u)),x=fa[x];
  84. printf("%d\n",ans);
  85. }
  86. return 0;
  87. }

[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. 完美解决 No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android

    问题描述 好久之前的一个Android项目,最近需要重构一下 因为Android Studio的开发环境以及Gradle的版本等等都进行了一定的更新,于是导入Project以后,出现了报错: No t ...

  2. cygwin 获取root高级权限

    cygwin安装完成后没有passwd文件解决方法 ​

  3. 手机APP测试环境搭建---appium

    这些都不是重点---一切都可以参考虫师   Appium移动自动化测试(一)--安装Appium 1.ADB的安装:ADB(ANDROID DEBUG BRIDGE) 应用场景: 针对移动端 Andr ...

  4. hdu1520树形dp第一题

    判断最大的欢喜值,如果上司来了,直系下属就不来 如果子节点j不来那么dp[i][1]+=dp[j][0];如果子节点j来那么dp[i][0]+=max(dp[j][0],dp[j][1]);//因为j ...

  5. nyi63——树

    #include<bits/stdc++.h> using namespace std; int cnt; struct node { int data; int flag; node * ...

  6. NC 工具的使用教程

    NC工具的使用说明...nc使用说明 参数介绍: nc.exe -h即可看到各参数的使用方法. 基本格式:nc [-options] hostname port[s] [ports] ... nc - ...

  7. IOS-数据缓存

    一.关于同一个URL的多次请求 有时候,对同一个URL请求多次,返回的数据可能都是一样的,比如服务器上的某张图片,无论下载多少次,返回的数据都是一样的. 上面的情况会造成以下问题 (1)用户流量的浪费 ...

  8. Python不同版本切换

    2016年6月8日更新: 这是我早前写的一篇小文章,其实,后来也没有采用这种方法切换.电脑上安装了多个Python 版本,保证自己经常用的版本加入环境变量外,使用非系统的版本时一般使用 IDE 编辑器 ...

  9. Ansible 小手册系列 十二(Facts)

    Facts 是用来采集目标系统信息的,具体是用setup模块来采集得. 使用setup模块来获取目标系统信息 ansible hostname -m setup 仅显示与ansible相关的内存信息 ...

  10. Esper——内存计算、事件驱动、SQL支持

    教程简介Esper是一个事件流处理(ESP)和事件关联引擎(CEP的,复杂事件处理).Esper的目标是针对实时事件驱动架构(EDA).当Esper监测到事件流中又符合条件的时间发生时,即可触发Pla ...