博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[CF983E]NN country
阅读量:6708 次
发布时间:2019-06-25

本文共 2655 字,大约阅读时间需要 8 分钟。

题意:给一棵树,有许多条巴士线路$(a_i,b_i)$(巴士在路径上每个点都会停车),多次询问从一点到另一点最少要坐多少次巴士

首先dfs一遍预处理出一个点向上坐$2^k$次巴士能到的最浅点,于是我们能很快地查询一个点往上走到另一个点最少要坐多少次巴士

对于询问$(u,v)$,我们肯定是贪心地坐车,每次坐尽可能远,路径是$u\rightarrow lca_{u,v}\rightarrow v$,我们找到$l_u$表示从$u$开始坐$a$次巴士能到的最浅点,并且再坐一次巴士就能到$lca_{u,v}$,同理坐$b$次巴士到$l_v$

那么如果有线路覆盖$(l_u,l_v)$,那么答案就是$a+b+1$,否则答案是$a+b+2$

考虑离线处理路径覆盖问题,一次dfs即可解决:假设当前节点是某个询问的$l_u$,我们先查询$l_v$的子树和并记下来,然后将所有从$l_u$开始的巴士路线的终点权值$+1$,递归进儿子,最后再查询一次$l_v$的子树和,如果它和之前查询过的值不同,那么说明有巴士线路覆盖$(l_u,l_v)$,否则没有,这个过程用树状数组维护dfs序即可

我写得又慢又丑qwq真实滥用STL

upd:这可能就是dsu on tree?

#include
#include
using namespace std;int h[200010],nex[200010],to[200010],in[200010],ou[200010],dep[200010],fa[200010][18],up[200010][18],M;void add(int a,int b){ M++; to[M]=b; nex[M]=h[a]; h[a]=M;}void dfs(int x){ M++; in[x]=M; dep[x]=dep[fa[x][0]]+1; for(int i=h[x];i;i=nex[i])dfs(to[i]); ou[x]=M;}int lca(int x,int y){ int i; if(dep[x]
=0;i--){ if(dep[fa[x][i]]>=dep[y])x=fa[x][i]; } if(x==y)return x; for(i=17;i>=0;i--){ if(fa[x][i]!=fa[y][i]){ x=fa[x][i]; y=fa[y][i]; } } return fa[x][0];}struct pr{ int x,y; pr(int a=0,int b=0){x=a;y=b;}};vector
bg[200010];void merge(int&x,int y){ if(x==0||y==0) x|=y; else if(dep[y]
=0;i--){ if(dep[up[x][i]]>dep[y]){ x=up[x][i]; t.y|=1<
ques[200010];int lowbit(int x){return x&-x;}int query(int x){ int res=0; while(x){ res+=s[x]; x-=lowbit(x); } return res;}int query(int l,int r){ return query(r)-query(l-1);}void modify(int x){ while(x<=n){ s[x]++; x+=lowbit(x); }}void dfs3(int x){ vector
v; vector
::iterator it; for(pr t:ques[x])v.push_back(query(in[t.x],ou[t.x])); for(pr t:bg[x])modify(in[t.x]); for(int i=h[x];i;i=nex[i])dfs3(to[i]); it=v.begin(); for(pr t:ques[x]){ if(*it==query(in[t.x],ou[t.x]))ans[t.y]++; it++; }}int main(){ int m,q,i,j,x,y; pr tx,ty; scanf("%d",&n); for(i=2;i<=n;i++){ scanf("%d",fa[i]); add(fa[i][0],i); } M=0; dfs(1); for(j=1;j<18;j++){ for(i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1]; } scanf("%d",&m); while(m--){ scanf("%d%d",&x,&y); j=lca(x,y); bg[x].push_back(pr(y,j)); bg[y].push_back(pr(x,j)); } dfs2(1); for(j=1;j<18;j++){ for(i=1;i<=n;i++)up[i][j]=up[up[i][j-1]][j-1]; } scanf("%d",&q); for(i=1;i<=q;i++){ scanf("%d%d",&x,&y); j=lca(x,y); tx=bus(x,j); ty=bus(y,j); if(x==j){ if(up[ty.x][0]==0) ans[i]=-1; else ans[i]=ty.y+1; }else if(y==j){ if(up[tx.x][0]==0) ans[i]=-1; else ans[i]=tx.y+1; }else{ if(up[tx.x][0]==0||up[ty.x][0]==0) ans[i]=-1; else{ ans[i]=tx.y+ty.y+1; ques[tx.x].push_back(pr(ty.x,i)); } } } dfs3(1); for(i=1;i<=q;i++)printf("%d\n",ans[i]);}

转载于:https://www.cnblogs.com/jefflyy/p/9135588.html

你可能感兴趣的文章
共享适合移动端的“拾色器”插件
查看>>
《Java编程思想》笔记09------异常处理
查看>>
CPU发生异常到生成Crash Log的过程
查看>>
pyqt5中动画的使用
查看>>
到底什么才是业务架构?
查看>>
基础设施即代码:Terraform和AWS无服务器
查看>>
Atlassian发布事故管理解决方案Jira Ops
查看>>
书评 —— 《Go语言编程》
查看>>
Apache HBase的现状和发展
查看>>
反模式的经典 - Mockito设计解析
查看>>
Zip Slip目录遍历漏洞已影响多个Java项目
查看>>
独家揭秘:微博深度学习平台如何支撑4亿用户愉快吃瓜?
查看>>
Visual Studio 15.7预览版4改进Git、C++支持
查看>>
全新云服务:亚马逊AWS发布AWS Ground Station\n
查看>>
微软宣布支持基于虚拟机的Azure IOT Edge服务
查看>>
来自社区的Visual Studio Code使用体验和教程
查看>>
高效运维最佳实践:如何做好On-call和事故响应?
查看>>
利用Scikit-Learn和Spark预测Airbnb的listing价格
查看>>
数据建模NoSQL数据库的概念和对象建模符号
查看>>
微软宣布Azure Function支持Python
查看>>