https://www.nowcoder.com/acm/contest/172/C

(sbw大佬太强啦 orz)

先把每一个路径(x,y)分成(x,lca),(y,lca)两个路径,然后就能发现,对于某两个(直上直下的)路径a,b,b的下端点在a的下端点子树中,且b的上端点深度<=a的上端点深度,那么b是覆盖a的。

这样的话,我们做一个dfs序,那么能覆盖某个路径的个数就是(下端点在dfs序对应的那个区间中的、上端点深度小于要覆盖的那个路径)的路径的个数。

而且比较容易发现,我们要求的其实就是dfs序那个区间里的深度第k小的路径。

这样的话,就可以搞一个主席树,以深度为权值,每条路径下端点的dfs序为时间往里加值,每次只要询问对应区间的第k小就可以。

不过要注意的是,我找出来的那个点深度大于我在做的这个点的深度的话,是不合法的,要判掉。

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define ll long long
using namespace std;
const int maxn=,logn=; ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,M,L,Q;
int lg[maxn],dep[maxn],fa[maxn][logn];
int egh[maxn],eg[maxn*][],ect;
int pth[maxn],pt[maxn*][],pct;
int id[maxn],dfn[maxn][],tot,lst[maxn];
int ch[maxn*logn*][],sum[maxn*logn*],root[maxn*],rct; inline void adeg(int a,int b){
eg[++ect][]=b;eg[ect][]=egh[a];egh[a]=ect;
}
inline void adpt(int a,int d){
pt[++pct][]=d;pt[pct][]=pth[a];pth[a]=pct;
} void dfs(int x){
dfn[x][]=++tot;id[tot]=x;
for(int i=;fa[x][i-]&&fa[fa[x][i-]][i-];i++){
fa[x][i]=fa[fa[x][i-]][i-];
}
for(int i=egh[x];i!=-;i=eg[i][]){
if(dfn[eg[i][]][]) continue;
dep[eg[i][]]=dep[x]+;fa[eg[i][]][]=x;
L=max(L,dep[x]+);dfs(eg[i][]);
}dfn[x][]=tot;
} inline int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
while(dep[x]>dep[y]){
x=fa[x][lg[dep[x]-dep[y]]];
}if(x==y) return x;
for(int i=lg[dep[x]-];i>=;i--){
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
}return fa[x][];
} void add(int &rn,int ro,int l,int r,int x){
rn=++rct;sum[rn]=sum[ro]+;
if(l<r){int m=l+r>>;
if(x<=m){
add(ch[rn][],ch[ro][],l,m,x);ch[rn][]=ch[ro][];
}else{
add(ch[rn][],ch[ro][],m+,r,x);ch[rn][]=ch[ro][];
}
}
}
int query(int rn,int ro,int l,int r,int k){
//printf("%d %d %d %d %d %d\n",l,r,rn,ro,sum[rn],sum[ro]);
if(k>sum[rn]-sum[ro]) return -;
if(l==r) return l;
else{
int m=l+r>>,w=sum[ch[rn][]]-sum[ch[ro][]];
if(w>=k) return query(ch[rn][],ch[ro][],l,m,k);
else return query(ch[rn][],ch[ro][],m+,r,k-w);
}
} inline int solve(int x,int k){
if(!k) return dep[x]-;
int y=query(root[lst[dfn[x][]]],root[lst[dfn[x][]-]],,L,k);
if(y==-||dep[x]<y) return ;
else return dep[x]-y;
} int main(){
//freopen("protect.in","r",stdin);
int i,j,k;
N=rd(),M=rd();memset(egh,-,sizeof(egh));
for(i=,j=,k=;i<=N+;i++){
if(i>=k) j++,k<<=;lg[i]=j;
}
for(i=;i<N;i++){
int a=rd(),b=rd();
adeg(a,b);adeg(b,a);
}dep[]=;dfs();memset(pth,-,sizeof(pth));
for(i=;i<=M;i++){
int a=rd(),b=rd();
int x=lca(a,b);
adpt(a,dep[x]);adpt(b,dep[x]);
}
for(i=,k=;i<=N;i++){
for(j=pth[id[i]];j!=-;j=pt[j][]){
++k;add(root[k],root[k-],,L,pt[j][]);
}lst[i]=k;
}
Q=rd();
for(i=;i<=Q;i++){
int a=rd(),b=rd();
printf("%d\n",solve(a,b));
}
return ;
}

nowcoder172C 保护 (倍增lca+dfs序+主席树)的更多相关文章

  1. 【bzoj3545/bzoj3551】[ONTAK2010]Peaks/加强版 Kruskal+树上倍增+Dfs序+主席树

    bzoj3545 题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询 ...

  2. 【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...

  3. 2018.09.30 bzoj3551:Peaks加强版(dfs序+主席树+倍增+kruskal重构树)

    传送门 一道考察比较全面的题. 这道题又用到了熟悉的kruskal+倍增来查找询问区间的方法. 查到询问的子树之后就可以用dfs序+主席树统计答案了. 代码: #include<bits/std ...

  4. dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448

    4448: [Scoi2015]情报传递 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 588  Solved: 308[Submit][Status ...

  5. 【bzoj1803】Spoj1487 Query on a tree III DFS序+主席树

    题目描述 You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node w ...

  6. [xdoj1216]子树第k小(dfs序+主席树)

    解题关键:dfs序将树映射到区间,然后主席树求区间第k小,为模板题. #pragma comment(linker, "/STACK:1024000000,1024000000") ...

  7. BZOJ 3439: Kpm的MC密码 (trie+dfs序主席树)

    题意 略 分析 把串倒过来插进trietrietrie上, 那么一个串的kpmkpmkpm串就是这个串在trietrietrie上对应的结点的子树下面的所有字符串. 那么像 BZOJ 3551/354 ...

  8. BZOJ 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+dfs序+主席树+倍增

    建出来 $Kruskal$ 重构树. 将询问点向上跳到深度最小,且合法的节点上. 那么,得益于重构树优美的性质,这个最终跳到的点为根的所有子节点都可以与询问点互达. 对于子树中求点权第 $k$ 大的问 ...

  9. 【BZOJ3772】精神污染 DFS序+主席树

    [BZOJ3772]精神污染 Description 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是 ...

随机推荐

  1. Java 基础之一对象导论

    对象导论 1.1 抽象过程 所有编程语言都提供抽象机制.人们所能解决的问题的复杂性直接取决于抽象的类型和质量. 汇编语言是对底层机器的轻微抽象. 我们将问题空间中的元素及其再解空间中的表示称为对象.这 ...

  2. centos下升级git版本的操作记录

    在使用git pull.git push.git clone的时候,或者在使用jenkins发版的时候,可能会报类似如下的错误: error: The requested URL returned e ...

  3. D. Little C Loves 3 II

    传送门 [http://codeforces.com/contest/1047/problem/D] 题意 给你n*m得棋盘,让你找两点之间距离为3的点的个数,不能重复使用,距离定义,两坐标差绝对值之 ...

  4. [BUAA软工]第二次博客作业---结对编程

    [BUAA软工]结对作业 项目 内容 这个作业属于哪个课程 北航软工 这个作业的要求在哪里 2019年软件工程基础-结对项目作业 我在这个课程的目标是 学习如何以团队的形式开发软件,提升个人软件开发能 ...

  5. 第三个spring冲刺第4天

    今天,我们在难度选择方面做了谈论,根据难度选择题目的难易和数量,在计时器方面应该有相应的配合,由此决定难易度,因此,我们要做好谈论,为这个难易度做好准备去编译,以免出现混乱.

  6. Markdown页内跳转实现方法

    目录 Markdown页内跳转实现方法 HTML锚点跳转 生成目录 Markdown页内跳转实现方法 [时间:2017-02] [状态:Open] [关键词:markdown,标记语言,页内跳转,ht ...

  7. java mail session使用Properties的clone方法

    /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreem ...

  8. linux命令学习head和tail

    linux命令head和tail是一对:more和less是一对. head和tail https://www.2cto.com/os/201507/414753.html 一个头,一个尾. tail ...

  9. Character Encoding Issues for tomcat

    https://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q8 https://stackoverflow.com/questions/10936846 ...

  10. C#微信公众号开发入门教程

    首先打开开发文档: 微信公众号开发者文档:http://mp.weixin.qq.com/wiki/home/index.html 一.创建测试账号 可以先申请一个开发者测试账号