传送门

题意:给一棵大树,令一棵模板树与这棵树相同,然后进行mmm次操作,每次选择模板树中的一个节点aaa和大树中一个节点bbb,把aaa这棵子树接在bbb上面,节点编号顺序跟aaa中的编号顺序相同。

最后有qqq次询问问大树上两点距离。


思路:

真·树套树

把每棵树所成一个点,然后相当于先把两个点跳到一个块中再求它们的lcalcalca,可以用主席树维护块中编号第kkk大来维护块中对应点,实现块于块之间的跳跃可以用倍增

  1. #include<bits/stdc++.h>
  2. #define ri register int
  3. using namespace std;
  4. const int rlen=1<<18|1;
  5. inline char gc(){
  6. static char buf[rlen],*ib,*ob;
  7. (ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
  8. return ib==ob?-1:*ib++;
  9. }
  10. typedef long long ll;
  11. inline ll read(){
  12. ll ans=0;
  13. char ch=gc();
  14. while(!isdigit(ch))ch=gc();
  15. while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
  16. return ans;
  17. }
  18. const int N=1e5+5;
  19. int rt[N],pred[N],Dep[N],num[N],top[N],hson[N],dep[N],fa[N],siz[N],st[N][20],n,m,q,tot=0;
  20. ll dis[N];
  21. vector<int>e[N];
  22. struct Node{int id;ll l,r,pre;}a[N];
  23. namespace sgt{
  24. #define lc son[p][0]
  25. #define rc son[p][1]
  26. #define mid (l+r>>1)
  27. int siz[N*30],son[N*30][2],tot=0;
  28. inline void update(int&p,int last,int l,int r,int k){
  29. siz[p=++tot]=siz[last]+1,lc=son[last][0],rc=son[last][1];
  30. if(l==r)return;
  31. k<=mid?update(lc,son[last][0],l,mid,k):update(rc,son[last][1],mid+1,r,k);
  32. }
  33. inline int query(int pl,int pr,int l,int r,int k){
  34. if(l==r)return l;
  35. int tmp=siz[son[pr][0]]-siz[son[pl][0]];
  36. return tmp>=k?query(son[pl][0],son[pr][0],l,mid,k):query(son[pl][1],son[pr][1],mid+1,r,k-tmp);
  37. }
  38. #undef lc
  39. #undef rc
  40. #undef mid
  41. }
  42. void dfs1(int p){
  43. siz[p]=1;
  44. for(ri i=0,v;i<e[p].size();++i){
  45. if((v=e[p][i])==fa[p])continue;
  46. fa[v]=p,dep[v]=dep[p]+1,dfs1(v),siz[p]+=siz[v];
  47. if(siz[v]>siz[hson[p]])hson[p]=v;
  48. }
  49. }
  50. void dfs2(int p,int tp){
  51. top[p]=tp,pred[num[p]=++tot]=p;
  52. if(!hson[p])return;
  53. dfs2(hson[p],tp);
  54. for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i])!=hson[p]&&v!=fa[p])dfs2(v,v);
  55. }
  56. inline int lca(int x,int y){
  57. while(top[x]^top[y]){
  58. if(dep[top[x]]<dep[top[y]])swap(x,y);
  59. x=fa[top[x]];
  60. }
  61. return dep[x]<dep[y]?x:y;
  62. }
  63. inline int find(ll x,int R){
  64. int l=1,r=R,ret=R;
  65. while(l<=r){
  66. int mid=l+r>>1;
  67. if(a[mid].r>=x)ret=mid,r=mid-1;
  68. else l=mid+1;
  69. }
  70. return ret;
  71. }
  72. inline ll dist(int blo,int x){return dis[blo]+dep[x]-dep[a[blo].id];}
  73. inline int idx(int blo,ll x){
  74. int t=a[blo].id;
  75. return sgt::query(rt[num[t]-1],rt[num[t]+siz[t]-1],1,n,x-a[blo].l+1);
  76. }
  77. inline int Lca(int x,int y){
  78. if(Dep[x]<Dep[y])swap(x,y);
  79. for(ri tmp=Dep[x]-Dep[y],i=19;~i;--i)if((tmp>>i)&1)x=st[x][i];
  80. if(x==y)return x;
  81. for(ri i=19;~i;--i)if(st[x][i]^st[y][i])x=st[x][i],y=st[y][i];
  82. return st[x][0];
  83. }
  84. inline int Find(int x,int k){
  85. for(ri i=19;~i;--i)if((k>>i)&1)x=st[x][i];
  86. return idx(st[x][0],a[x].pre);
  87. }
  88. inline ll calc(int fx,int fy,int x,int y){
  89. int t=Lca(fx,fy);
  90. if(fx==t)swap(fx,fy),swap(x,y);
  91. if(fy==t){
  92. ll ret=dist(fx,x);
  93. ret-=dist(t,x=Find(fx,Dep[fx]-Dep[t]-1));
  94. return ret+dep[x]+dep[y]-2*dep[lca(x,y)];
  95. }
  96. ll ret=dist(fx,x)+dist(fy,y);
  97. ret-=dist(t,x=Find(fx,Dep[fx]-Dep[t]-1));
  98. ret-=dist(t,y=Find(fy,Dep[fy]-Dep[t]-1));
  99. return ret+dep[x]+dep[y]-2*dep[lca(x,y)];
  100. }
  101. int main(){
  102. n=read(),m=read()+1,q=read();
  103. for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
  104. dfs1(1),dfs2(1,1);
  105. for(ri i=1;i<=n;++i)sgt::update(rt[i],rt[i-1],1,n,pred[i]);
  106. a[1]=(Node){1,1,n,0};
  107. ll x,y,Tot=n;
  108. for(ri i=2;i<=m;++i){
  109. x=read(),y=read();
  110. a[i]=(Node){x,Tot+1,Tot+siz[x],y},Tot+=siz[x];
  111. st[i][0]=find(y,i-1),Dep[i]=Dep[st[i][0]]+1,dis[i]=dis[st[i][0]]+dep[idx(st[i][0],y)]-dep[a[st[i][0]].id]+1;
  112. }
  113. for(ri j=1;j<20;++j)for(ri i=1;i<=m;++i)st[i][j]=st[st[i][j-1]][j-1];
  114. while(q--){
  115. x=read(),y=read();
  116. int fx=find(x,m),fy=find(y,m);
  117. x=idx(fx,x),y=idx(fy,y);
  118. if(fx^fy)cout<<calc(fx,fy,x,y)<<'\n';
  119. else cout<<dep[x]+dep[y]-2*dep[lca(x,y)]<<'\n';
  120. }
  121. }

2019.03.25 bzoj4539: [Hnoi2016]树(主席树+倍增)的更多相关文章

  1. 2019.03.25 bzoj4568: [Scoi2016]幸运数字(倍增+线性基)

    传送门 题意:给你一棵带点权的树,多次询问路径的最大异或和. 思路: 线性基上树?? 倍增维护一下就完了. 时间复杂度O(nlog3n)O(nlog^3n)O(nlog3n) 代码: #include ...

  2. 线段树简单入门 (含普通线段树, zkw线段树, 主席树)

    线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...

  3. [2019.03.25]Linux中的查找

    TMUX天下第一 全世界所有用CLI Linux的人都应该用TMUX,我爱它! ======================== 以下是正文 ======================== Linu ...

  4. [BZOJ4539][HNOI2016]树(主席树)

    4539: [Hnoi2016]树 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 746  Solved: 292[Submit][Status][D ...

  5. BZOJ 4539: [Hnoi2016]树 [主席树 lca]

    4539: [Hnoi2016]树 题意:不想写.复制模板树的子树,查询两点间距离. *** 终于有一道会做的题了...... 画一画发现可以把每次复制的子树看成一个大点来建一棵树,两点的lca一定在 ...

  6. Luogu5289 十二省联考2019字符串问题(后缀数组+拓扑排序+线段树/主席树/KDTree)

    先考虑80分做法,即满足A串长度均不小于B串,容易发现每个B串对应的所有A串在后缀数组上都是一段连续区间,线段树优化连边然后判环求最长链即可.场上就写了这个. 100分也没有什么本质区别,没有A串长度 ...

  7. bzoj 4539 [Hnoi2016]树——主席树+倍增

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4539 明明就是把每次复制的一个子树当作一个点,这样能连出一个树的结构,自己竟然都没想到.思维 ...

  8. [POJ2104] K – th Number (可持久化线段树 主席树)

    题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...

  9. 【BZOJ3439】Kpm的MC密码 trie树+主席树

    Description 背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当然地忘记了密码,只能来解答那些神奇的身 ...

随机推荐

  1. 【转】WPS word 文档中的插入对象 为什么打不开

    点击桌面左下角开始按钮--所有程序,找到wps office文件夹--wps office工具--配置工具--高级--兼容设置,否选兼容第三方软件.

  2. inpuy只能输入数字,并且禁止输入e

    <el-input type="number" onkeyup="this.value=this.value.replace(/[^\d]/g,'')" ...

  3. javascript正则表达式分组捕获理解

    我们先来看一段js代码: var rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/; console.log(rquickExpr.ex ...

  4. Jquery中小数取整

    var uu=Math.floor(5.36) 向下取整 结果为5 var uu=Math.floor(5.88) 结果为5 Math.ceil(5.33) 向上取整,结果为6 Math.round( ...

  5. linux大文件读取

    在生产环境中有时候可能会遇到大文件的读取问题,但是大文件读取如果按照一般的手法.如cat这种都是对io的一个挑战,如果io扛得住还好,如果扛不住 造成的后果,如服务器内存奔溃,日志损坏 方法一: se ...

  6. 解决git中upstream丢失问题Your branch is based on 'origin/xxxx', but the upstream is gone.

    转自 https://blog.csdn.net/limengke123/article/details/77850134

  7. Java框架spring 学习笔记(八):注入对象类型属性

    使用set方法注入对象属性 编写UserDao.java文件 package com.example.spring; public class UserDao { public void print( ...

  8. 对于在git上面拉代码报"error: RPC failed; curl 56 OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 10054"解决方法

    主要原因是安全设置的问题: 首先执行git config http.sslVerify "false"   若出现下列错误 git config http.sslVerify &q ...

  9. 一些用Css实现的效果

    今天写一个笔试题,其中有一个是用css实现直角梯形的效果,我给出的答案是: <style> .wrap{ width: 100px; height: 50px; border-top:90 ...

  10. 100-days: twenty-three

    Title: The surprising connection between single women and gentrification connection n.连接,联系,关系:连接点; ...