nowcoder172C 保护 (倍增lca+dfs序+主席树)
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序+主席树)的更多相关文章
- 【bzoj3545/bzoj3551】[ONTAK2010]Peaks/加强版  Kruskal+树上倍增+Dfs序+主席树
		
bzoj3545 题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询 ...
 - 【bzoj1146】[CTSC2008]网络管理Network  倍增LCA+dfs序+树状数组+主席树
		
题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...
 - 2018.09.30 bzoj3551:Peaks加强版(dfs序+主席树+倍增+kruskal重构树)
		
传送门 一道考察比较全面的题. 这道题又用到了熟悉的kruskal+倍增来查找询问区间的方法. 查到询问的子树之后就可以用dfs序+主席树统计答案了. 代码: #include<bits/std ...
 - dfs序+主席树   或者   树链剖分+主席树(没写)   或者  线段树套线段树   或者  线段树套splay   或者  线段树套树状数组   bzoj 4448
		
4448: [Scoi2015]情报传递 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 588 Solved: 308[Submit][Status ...
 - 【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 ...
 - [xdoj1216]子树第k小(dfs序+主席树)
		
解题关键:dfs序将树映射到区间,然后主席树求区间第k小,为模板题. #pragma comment(linker, "/STACK:1024000000,1024000000") ...
 - BZOJ 3439: Kpm的MC密码 (trie+dfs序主席树)
		
题意 略 分析 把串倒过来插进trietrietrie上, 那么一个串的kpmkpmkpm串就是这个串在trietrietrie上对应的结点的子树下面的所有字符串. 那么像 BZOJ 3551/354 ...
 - BZOJ 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+dfs序+主席树+倍增
		
建出来 $Kruskal$ 重构树. 将询问点向上跳到深度最小,且合法的节点上. 那么,得益于重构树优美的性质,这个最终跳到的点为根的所有子节点都可以与询问点互达. 对于子树中求点权第 $k$ 大的问 ...
 - 【BZOJ3772】精神污染 DFS序+主席树
		
[BZOJ3772]精神污染 Description 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是 ...
 
随机推荐
- OpenBLAS简介及在Windows7 VS2013上源码的编译过程
			
OpenBLAS(Open Basic Linear Algebra Subprograms)是开源的基本线性代数子程序库,是一个优化的高性能多核BLAS库,主要包括矩阵与矩阵.矩阵与向量.向量与向量 ...
 - 使用Hexo+Github搭建属于自己的博客(基础)
			
前言 hexo是一个台湾人做的基于Node.js的静态博客程序,优势是生成静态文件的速度非常快,支持markdown, 我最终选定它的原因是它速度快而且不容易出错,并且可以一键部署到github或者其 ...
 - mybatis源码-解析配置文件(四)之配置文件Mapper解析
			
在 mybatis源码-解析配置文件(三)之配置文件Configuration解析 中, 讲解了 Configuration 是如何解析的. 其中, mappers作为configuration节点的 ...
 - 使用canvas实现一个圆球的触壁反弹
			
HTML <canvas id="canvas" width="500" height="500" style="borde ...
 - c#基础系列1---深入理解值类型和引用类型
			
"大菜":源于自己刚踏入猿途混沌拾起,自我感觉不是一般的菜,因而得名"大菜",于自身共勉. 不知不觉已经踏入坑已10余年之多,对于c#多多少少有一点自己的认识, ...
 - VS2013安装和单元测试
			
1. VC2013安装过程及使用感受 刚上大一的时候老师推荐我们用VC++6.0.当时也就听了老师的话用VC++6.0编程了一段时间.后来上了大二买了电脑VC++6.0支持不了WIN8.1所以我就开始 ...
 - M2事后分析
			
计划 1. 你原计划的工作是否最后都做完了? 如果有没做完的,为什么? 修复了M1阶段的bug,整合前两组的数据.扩充功能,和学霸组达成功能上的一致,对数据库进行信息的完善. 2. 有没有发现你做了一 ...
 - Linux基础实践
			
Linux基础实践 1.1 应用安装 要求:掌握软件源的维护方法,配置系统使用软件源镜像.掌握通过软件源来查找,安装,卸载,更新软件的方法 备份原地址列表文件:sudo cp /etc/apt/sou ...
 - Linux实践:ELF文件格式分析
			
标签(空格分隔): 20135321余佳源 一.基础知识 ELF全称Executable and Linkable Format,可执行连接格式,ELF格式的文件用于存储Linux程序.ELF文件(目 ...
 - LINUX内核分析第六周学习总结——进程的描述与创建
			
LINUX内核分析第六周学习总结--进程的描述与创建 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc ...