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小就可以。
不过要注意的是,我找出来的那个点深度大于我在做的这个点的深度的话,是不合法的,要判掉。
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define ll long long 4 using namespace std; 5 const int maxn=200020,logn=22; 6 7 ll rd(){ 8 ll x=0;char c=getchar();int neg=1; 9 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 10 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 11 return x*neg; 12 } 13 14 int N,M,L,Q; 15 int lg[maxn],dep[maxn],fa[maxn][logn]; 16 int egh[maxn],eg[maxn*2][2],ect; 17 int pth[maxn],pt[maxn*2][2],pct; 18 int id[maxn],dfn[maxn][2],tot,lst[maxn]; 19 int ch[maxn*logn*8][2],sum[maxn*logn*8],root[maxn*2],rct; 20 21 inline void adeg(int a,int b){ 22 eg[++ect][0]=b;eg[ect][1]=egh[a];egh[a]=ect; 23 } 24 inline void adpt(int a,int d){ 25 pt[++pct][0]=d;pt[pct][1]=pth[a];pth[a]=pct; 26 } 27 28 void dfs(int x){ 29 dfn[x][0]=++tot;id[tot]=x; 30 for(int i=1;fa[x][i-1]&&fa[fa[x][i-1]][i-1];i++){ 31 fa[x][i]=fa[fa[x][i-1]][i-1]; 32 } 33 for(int i=egh[x];i!=-1;i=eg[i][1]){ 34 if(dfn[eg[i][0]][0]) continue; 35 dep[eg[i][0]]=dep[x]+1;fa[eg[i][0]][0]=x; 36 L=max(L,dep[x]+1);dfs(eg[i][0]); 37 }dfn[x][1]=tot; 38 } 39 40 inline int lca(int x,int y){ 41 if(dep[x]<dep[y]) swap(x,y); 42 while(dep[x]>dep[y]){ 43 x=fa[x][lg[dep[x]-dep[y]]]; 44 }if(x==y) return x; 45 for(int i=lg[dep[x]-1];i>=0;i--){ 46 if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; 47 }return fa[x][0]; 48 } 49 50 void add(int &rn,int ro,int l,int r,int x){ 51 rn=++rct;sum[rn]=sum[ro]+1; 52 if(l<r){int m=l+r>>1; 53 if(x<=m){ 54 add(ch[rn][0],ch[ro][0],l,m,x);ch[rn][1]=ch[ro][1]; 55 }else{ 56 add(ch[rn][1],ch[ro][1],m+1,r,x);ch[rn][0]=ch[ro][0]; 57 } 58 } 59 } 60 int query(int rn,int ro,int l,int r,int k){ 61 //printf("%d %d %d %d %d %d\n",l,r,rn,ro,sum[rn],sum[ro]); 62 if(k>sum[rn]-sum[ro]) return -1; 63 if(l==r) return l; 64 else{ 65 int m=l+r>>1,w=sum[ch[rn][0]]-sum[ch[ro][0]]; 66 if(w>=k) return query(ch[rn][0],ch[ro][0],l,m,k); 67 else return query(ch[rn][1],ch[ro][1],m+1,r,k-w); 68 } 69 } 70 71 inline int solve(int x,int k){ 72 if(!k) return dep[x]-1; 73 int y=query(root[lst[dfn[x][1]]],root[lst[dfn[x][0]-1]],1,L,k); 74 if(y==-1||dep[x]<y) return 0; 75 else return dep[x]-y; 76 } 77 78 int main(){ 79 //freopen("protect.in","r",stdin); 80 int i,j,k; 81 N=rd(),M=rd();memset(egh,-1,sizeof(egh)); 82 for(i=1,j=0,k=2;i<=N+10;i++){ 83 if(i>=k) j++,k<<=1;lg[i]=j; 84 } 85 for(i=1;i<N;i++){ 86 int a=rd(),b=rd(); 87 adeg(a,b);adeg(b,a); 88 }dep[1]=1;dfs(1);memset(pth,-1,sizeof(pth)); 89 for(i=1;i<=M;i++){ 90 int a=rd(),b=rd(); 91 int x=lca(a,b); 92 adpt(a,dep[x]);adpt(b,dep[x]); 93 } 94 for(i=1,k=0;i<=N;i++){ 95 for(j=pth[id[i]];j!=-1;j=pt[j][1]){ 96 ++k;add(root[k],root[k-1],1,L,pt[j][0]); 97 }lst[i]=k; 98 } 99 Q=rd(); 100 for(i=1;i<=Q;i++){ 101 int a=rd(),b=rd(); 102 printf("%d\n",solve(a,b)); 103 } 104 return 0; 105 }
转载于:https://www.cnblogs.com/Ressed/p/9628631.html
nowcoder172C 保护 (倍增lca+dfs序+主席树)相关推荐
- HDU 6203 ping ping ping (在线倍增lca+DFS序+树状数组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6203 #include<bits/stdc++.h> using namespace st ...
- codeforces E. Jamie and Tree LCA+dfs序+线段树
题解: 写起来还稍微有点麻烦. dfs序+线段树可以维护子树的整体修改和查询. 因此,这道题我们要往子树上靠. 我们首先从1号点进行dfs遍历,顺便求出点的dfs序和深度,然后我们采用倍增的思想,可以 ...
- 洛谷 - P4197 Peaks(Kruskal重构树+dfs序+主席树)
题目链接:点击查看 题目大意:有 n 座山峰,每座山峰有他的高度 h[ i ] ,有些山峰之间有双向道路相连,共 m 条路径,每条路径有一个困难值,这个值越大表示越难走. 现在有 q 组询问,每组询问 ...
- HDU - 6203 ping ping ping(LCA+dfs序+线段树)
题目链接:点击查看 题目大意:给出一棵由n+1个节点组成的数,节点编号为0~n(这个无关紧要,预处理时所有节点以及n都自增1即可转换为正常的模型了),现在给出m组节点u和v,问若想让m组u和v都断开连 ...
- POJ - 2763 Housewife Wind LCA+dfs序+线段树
q次询问求两个点之间的距离,并且可以随时修改某条边的长度,最短距离可以用lca来求,但是树上维护每一个点到root的距离必须要用dfs序来记录时间戳,在dfs的时候顺便记录每一条边(u,v)对应的v节 ...
- 洛谷 - P3899 [湖南集训]谈笑风生(dfs序+主席树/二维数点)
题目链接:点击查看 题目大意:设 TTT 为一棵有根树,我们做如下的定义: 设 aaa 和 bbb 为 TTT 中的两个不同节点.如果 aaa 是 bbb 的祖先,那么称"aaa 比 bbb ...
- 【BZOJ3439】Kpm的MC密码,trie树+dfs序+主席树
Time:2016.05.07 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 1.have a trie,还得是倒着建的,记录每个结尾节点的id(可能会有重复,所以开一个vecto ...
- 2021牛客多校7 - xay loves trees(dfs序+主席树-标记永久化)
题目链接:点击查看 题目大意:给出两棵以点 111 为根节点的有根树,现在要求满足条件的最大集合: 在第一棵树中,集合内的任意两个点都必须满足祖先关系,即 uuu 是 vvv 的祖先或 vvv 是 u ...
- 2021牛客暑期多校训练营7 xay loves trees dfs序 + 主席树
传送门 文章目录 题意: 思路: 题意: 给你两棵树,让你在第一棵树选一条最长的深度递增的链,链上每一个点在第二棵树上都不互为祖先. n≤3e5n\le3e5n≤3e5 思路: 之前做过差不多的题传送 ...
最新文章
- android使用webview上传文件,Android项目中如何在webview页面中上传文件
- Oracle专家调优秘密
- IE工具条不能自动显示
- dwz框架中动态添加查找带回组件
- Go--4大基本数据类型之布尔类型
- apache http server 停止工作_宝塔apache启动失败:报错 AH00526: Syntax error on line 解决方案...
- 金蝶kis仓库管理系统演示_金蝶KIS专业版生产管理的系统亮点功能
- 今天加入了“宇宙通史:木星”
- 机器学习的基本概念和相关术语
- ofo 回应甩卖办公桌;华为与袁隆平合作;罗永浩 1 亿股权遭冻结 | 极客头条
- python基本内容讲解_Python命名约定基本内容解析
- android下载模块封装,AndroidStudio 3.0 NDK开发2-AAR模块封装
- javascript数据结构——栈
- Python 从零开始制作自己的声音 - wave模块读写wav文件详解
- 破解vba工程密码——VBA代码
- 【打卡帖】7日玩转ESP32——(第5日) 通过串口的WiFi 配网
- 用python操作浏览器的三种方式_经验 | python 操作浏览器的三种方式
- webpack 拾翠:充分利用 CommonsChunkPlugin()
- js(javascript)和jq(jquery)常见问题(持续更新)
- Python: 使用sphinx生成python项目文档
热门文章
- centos6.5 rpm安装mysql_CentOS6.5系统下RPM包安装MySQL5.6(转)
- 语言逻辑运算符两侧运算对象_5.3 C语言逻辑运算符与表达式
- java学习笔记_Java学习笔记day11
- thinkphp json_原创干货 | Thinkphp序列化合总
- 计算机实现数论 奇偶排列问题
- linux查询设备文件信息失败怎么办,Linux下使用blkid命令查询设备及文件系统信息的方法...
- python使用欧氏距离knn_python运用sklearn实现KNN分类算法
- mysql g月份分组_PowerBI快捷键——视觉对象分组功能
- python程序、画一个笑脸_如何使用canvas画一个微笑的表情(代码示例)
- PCM设备能在公网使用吗?