https://www.luogu.org/problemnew/show/P3248

题解

模拟题意即可,把每次接过去的子树看做一个点,然后这个关系构成了一棵树。

大力倍增即可。

代码

#include<bits/stdc++.h>
#define N 100009
#define ls tr[cnt].l
#define rs tr[cnt].r
using namespace std;
typedef long long ll;
int p[20][N],deep[N],tot,head[N],n,m,q,tott,dep[N],pr[20][N],T[N],size[N],c[N],pre[N];
ll dis[20][N],noww,b[N],nowid;
inline ll rd(){ll x=0;char c=getchar();bool f=0;while(!isdigit(c)){if(c=='-')f=1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}return f?-x:x;
}
struct node{int l,r,size;
}tr[N*40];
struct edge{int n,to;}e[N<<1];
inline void add(int u,int v){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;}
inline void ins(int &cnt,int l,int r,int id){cnt=++tott;tr[cnt].size++;if(l==r)return;int mid=(l+r)>>1;if(mid>=id)ins(ls,l,mid,id);else ins(rs,mid+1,r,id);
}
int merge(int u,int v){if(!u||!v)return u^v;int cnt=++tott;tr[cnt].size=tr[u].size+tr[v].size;ls=merge(tr[u].l,tr[v].l);rs=merge(tr[u].r,tr[v].r);return cnt;
}
inline int kth(int &cnt,int l,int r,int k){int mid=(l+r)>>1;if(l==r)return l;if(tr[ls].size<k)return kth(rs,mid+1,r,k-tr[ls].size);else return kth(ls,l,mid,k);
}
void dfs(int u,int fa){ins(T[u],1,n,u);size[u]=1;for(int i=1;(1<<i)<=deep[u];++i)p[i][u]=p[i-1][p[i-1][u]];for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){int v=e[i].to;deep[v]=deep[u]+1;p[0][v]=u;dfs(v,u);size[u]+=size[v];T[u]=merge(T[u],T[v]); }
}
inline int getlca(int u,int v){if(deep[u]<deep[v])swap(u,v);for(int i=19;i>=0;--i)if(deep[u]-(1<<i)>=deep[v])u=p[i][u];if(u==v)return u;for(int i=19;i>=0;--i)if(p[i][u]!=p[i][v])u=p[i][u],v=p[i][v];return p[0][u];
}
inline int jump(int x,int xx){for(int i=19;i>=0;--i)if((1<<i)&xx)x=pr[i][x];return x;
}
int main(){n=rd();m=rd();q=rd();ll u,v;for(int i=1;i<n;++i){u=rd();v=rd();add(u,v);add(v,u);}dfs(1,0);b[++b[0]]=1;noww=n;c[b[0]]=1;nowid=1;while(m--){u=rd();v=rd();b[++b[0]]=noww+1;noww+=size[u];c[b[0]]=u;int x=upper_bound(b+1,b+b[0]+1,v)-b-1;int preid=x,preroot=c[x],now=kth(T[preroot],1,n,v-b[x]+1);//preid 被接的树的编号 preroot 被接的树的根 now被接的节点编号 //  cout<<x<<" "<<preroot<<" "<<now<<" "<<preid<<" biu \n"; ++nowid;pr[0][nowid]=preid;dis[0][nowid]=deep[now]-deep[preroot]+1;dep[nowid]=dep[preid]+1;pre[nowid]=now;for(int i=1;(1<<i)<=dep[nowid];++i)pr[i][nowid]=pr[i-1][pr[i-1][nowid]],dis[i][nowid]=dis[i-1][nowid]+dis[i-1][pr[i-1][nowid]];}while(q--){u=rd();v=rd();int x=upper_bound(b+1,b+b[0]+1,u)-b-1,y=upper_bound(b+1,b+b[0]+1,v)-b-1;int now1=kth(T[c[x]],1,n,u-b[x]+1),now2=kth(T[c[y]],1,n,v-b[y]+1);
//      cout<<x<<" "<<y<<"  "<<now1<<" "<<now2<<endl;       ll ans=0;if(x==y){ans=deep[now1]+deep[now2]-2*deep[getlca(now1,now2)];printf("%lld\n",ans);continue;}if(dep[x]<dep[y])swap(x,y),swap(now1,now2);int bu=dep[x]-dep[y];if(jump(x,bu)==y){int xx=bu-1;ans+=deep[now1]-deep[c[x]];         for(int i=19;i>=0;--i)if((1<<i)&xx){ans+=dis[i][x];x=pr[i][x];}ans++;ans+=deep[now2]+deep[pre[x]]-2*deep[getlca(now2,pre[x])];}else{ans+=deep[now1]-deep[c[x]]+deep[now2]-deep[c[y]];for(int i=19;i>=0;--i)if(dep[x]-(1<<i)>=dep[y]){ans+=dis[i][x];x=pr[i][x];}for(int i=19;i>=0;--i)if(pr[i][x]!=pr[i][y]){ans+=dis[i][x]+dis[i][y];x=pr[i][x];y=pr[i][y];}int dx=pre[x],dy=pre[y];ans+=2;//  cout<<x<<" "<<y<<" "<<pr[0][x]<<" "<<pr[0][y]<<"  ";ans+=deep[dx]+deep[dy]-2*deep[getlca(dx,dy)];}printf("%lld\n",ans);}return 0;
}

转载于:https://www.cnblogs.com/ZH-comld/p/10829898.html

[HNOI2016]树相关推荐

  1. BZOJ4539: [Hnoi2016]树

    BZOJ4539: [Hnoi2016]树 Description 小A想做一棵很大的树,但是他手上的材料有限,只好用点小技巧了. 开始,小A只有一棵结点数为N的树,结点的编号为1,2,-,N,其中结 ...

  2. 2019.03.25 bzoj4539: [Hnoi2016]树(主席树+倍增)

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

  3. linux下gem卸载,gem 安装卸载pod

    Linux打包压缩.md Linux下打包压缩命令 下面学习一下压缩和打包的相关命令,首先得先明确两个概念,即:压缩和打包 .我们实际使用中一般是打包和压缩结合的使用,为了学习下面简要的介绍一下压缩文 ...

  4. [暑假的bzoj刷水记录]

    (这篇我就不信有网站来扣) 这个暑假打算刷刷题啥的 但是写博客好累啊  堆一起算了 隔一段更新一下.  7月27号之前刷的的就不写了 , 写的累 代码不贴了,可以找我要啊.. 2017.8.27upd ...

  5. # HNOI2012 ~ HNOI2018 题解

    HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...

  6. 2018十二月刷题列表

    Preface \(2018\)年的尾巴,不禁感慨自己这一年的蜕变只能用蜕变来形容了. 而且老叶说我们今年没的参加清北冬令营可以参加CCF在广州二中举办的冬令营,只要联赛\(390+\)就应该可以报. ...

  7. P3250 [HNOI2016]网络(利用堆建线段树 + 树剖)

    P3250 [HNOI2016]网络 做法有点神奇!!!利用堆作为节点建立一颗线段树,用堆维护线段树上点的信息. 说说查询操作,我们的目的是要查询,没有经过这个点的事件最大值,考虑如何维护. 我们定义 ...

  8. [HNOI2016]网络(树链剖分+线段树+大根堆)

    [HNOI2016]网络 problem solution 另辟蹊径,不把交互请求赋在新增路径上,反而把交互请求赋在树上除去该请求路径覆盖点的其它点上 显然,路径问题树剖是非常可以的. 那么一个点上的 ...

  9. [HNOI2016]网络 树链剖分,堆

    [HNOI2016]网络 LG传送门 表示乱搞比正解难想. 整体二分很好想吧. 但是为了好写快乐,我们选择三个\(\log\)的乱搞. 先树剖,线段树套堆维护区间最大值.对于一次修改,如果是插入,就把 ...

  10. [HNOI2016] 序列(线段树 + 莫队 + 倍增)

    problem luogu-P3246 心路历程+卡常历程+问题存疑 一直在想莫队的做法.发现左右指针的移动对应一段左/右端点固定的子序列,然后可以一个数代表一段相同的贡献. 就开始求 lsti,nx ...

最新文章

  1. 【Hisi音频】Hi3520D音频输出调试
  2. typedef enum的用法(枚举)
  3. 【机器学习基础】超全汇总!机器学习常用术语词汇表(建议收藏)
  4. 北京阿里云ACE态势感知大屏体验黑客攻击与防御
  5. 图论--关于最长路的探讨
  6. C++中cin、cin.get()、cin.getline()、getline()等函数的用法
  7. C#使用Sockets操作FTP【转载】
  8. Android访问WCF服务(上篇)-服务端开发
  9. vim/nvim键盘映射
  10. 自动阅读专业版第九次更新---原薅羊毛专业版
  11. cmd查看自己的CPU参数
  12. 2549. 删除他们! 解题报告
  13. C#实战004:Excel操作-读取Excel工作簿
  14. Unity 事件中心
  15. 计算机组成原理字发生器,计算机组成原理实验2.7时序发生器赖晓铮剖析.ppt
  16. UDF开发手册 - UDF
  17. 360浏览器html位置,win7系统查看360浏览器收藏夹位置的操作方法
  18. pytest报错 E ModuleNotFoundError解决办法
  19. 【多肉】播种育苗 友情推荐:教你如何买到真种子
  20. win10家庭版安装docker后vm无法启动

热门文章

  1. mysql --force 无效_【技能库】--mysql 索引失效 force index也失效-- 原因解决方案(256)...
  2. 自我监督学习和无监督学习_弱和自我监督的学习-第2部分
  3. php视图,PHP的Yii框架中View视图的使用进阶
  4. mysql dump语句_mysql/mariadb知识点总结(28):mysql备份工具之mysqldump
  5. matlab平滑图像轮廓,Matlab 画平滑轮廓 print 高质量 figure
  6. php 替换数字和字母,php preg_替换非字母数字字符并选择连词,然后拆分
  7. ABAP function group和Tomcat library重复加载问题 1
  8. C#二进制文件读取序列化与反序列化
  9. 揭开阿里P2P面纱:大数据是泡泡
  10. Vuejs——(4)v-if、v-for