【LNOI2014】【BZOJ3626】NOIp2018模拟(三) LCA
Description
给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
设$dep[i]$表示点i的深度,$lca(i,j)$表示i与j的最近公共祖先。
有q次询问,每次询问给出l,r,z,求$\sum\limits_{i=l}^{r}dep[lca(i,z)]$。
(即求在$[l,r]$区间内的每个节点i与z的最近公共祖先的深度之和)
$n,q<=50000$
Input
第一行2个整数n,q。
接下来n-1行,分别表示点1到点n-1的父节点编号。
接下来q行,每行3个整数l,r,z。
Output
输出q行,每行表示一个询问的答案。每个答案对201314取模输出
Sample Input
5 2
0
0
1
1
1 4 3
1 4 2
Sample Output
8
5
这题不算很难,但是看到正解的方法很有趣,就记录一下~
考虑暴力,每次询问把z到根的所有节点打上标记,枚举i的时候直接往根找第一个有标记的点,然后统计深度即可。
然而复杂度明显是大于$O(n^2q)$的,显然不能接受,容易发现如果把深度看成点权,那么统计深度就相当于把z到根的每个节点权值都加一,然后枚举时统计根节点到i的权值和。使用树链剖分可以降到$O(nqlog^2n)$,但是还是会超时。
考虑进一步优化,发现询问可以差分,拆成$[1,l-1]$和$[1,r]$两个询问,进一步可以发现对答案有贡献的点只会在$lca(i,z)$以上,因此把每个i到根路径上的结点权值加一,再统计z到根节点的权值和,得出的答案是相同的。再结合差分,每次直接将$[1,l-1]$或$[1,r]$中所有节点到根节点路径上的点权值加一,然后统计z到根节点的权值和,按照dfs序区间修改+区间查询,用树链剖分加线段树可以做到$O(qlog^2n)$,用LCT可以做到$O(qlogn)$
注意long long
代码:
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #define mod 201314 7 using namespace std; 8 typedef long long ll; 9 struct edge{ 10 int v,next; 11 }a[200001]; 12 struct task{ 13 int r,z,id,ok; 14 }q[200001]; 15 int n,qq,u,v,z,tmp=0,qqq=0,tot=0,tim=0,head[100001],son[100001],siz[100001],fa[100001],dep[100001],dfn[100001],top[100001]; 16 ll t[500001],laz[500001],tv[500001],ans[100001],anss; 17 bool cmp(task a,task b){ 18 return a.r<b.r; 19 } 20 void add(int u,int v){ 21 a[++tot].v=v; 22 a[tot].next=head[u]; 23 head[u]=tot; 24 } 25 void dfs1(int u,int f,int dpt){ 26 dep[u]=dpt; 27 fa[u]=f; 28 siz[u]=1; 29 for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){ 30 int v=a[tmp].v; 31 if(!dep[v]){ 32 dfs1(v,u,dpt+1); 33 siz[u]+=siz[v]; 34 if(siz[v]>siz[son[u]]||son[u]==-1)son[u]=v; 35 } 36 } 37 } 38 void dfs2(int u,int tp){ 39 dfn[u]=++tim; 40 top[u]=tp; 41 if(son[u]!=-1)dfs2(son[u],tp); 42 for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){ 43 int v=a[tmp].v; 44 if(v!=son[u])dfs2(v,v); 45 } 46 } 47 void pushup(int u){ 48 t[u]=t[u*2]+t[u*2+1]; 49 } 50 void pushdown(int u){ 51 if(laz[u]){ 52 laz[u*2]+=laz[u]; 53 laz[u*2+1]+=laz[u]; 54 t[u*2]+=tv[u*2]*laz[u]; 55 t[u*2+1]+=tv[u*2+1]*laz[u]; 56 laz[u]=0; 57 } 58 } 59 void build(int l,int r,int u){ 60 if(l==r){ 61 tv[u]=1; 62 return; 63 } 64 int mid=(l+r)/2; 65 build(l,mid,u*2); 66 build(mid+1,r,u*2+1); 67 tv[u]=tv[u*2]+tv[u*2+1]; 68 } 69 void updata(int l,int r,int u,int L,int R,int v){ 70 if(L<=l&&r<=R){ 71 t[u]+=(ll)tv[u]*v; 72 laz[u]+=v; 73 return; 74 } 75 int mid=(l+r)/2; 76 pushdown(u); 77 if(L<=mid)updata(l,mid,u*2,L,R,v); 78 if(mid<R)updata(mid+1,r,u*2+1,L,R,v); 79 pushup(u); 80 } 81 ll query(int l,int r,int u,int L,int R){ 82 if(L<=l&&r<=R){ 83 return t[u]; 84 } 85 int mid=(l+r)/2,ans=0; 86 pushdown(u); 87 if(L<=mid)ans+=query(l,mid,u*2,L,R); 88 if(R>mid)ans+=query(mid+1,r,u*2+1,L,R); 89 return ans; 90 } 91 void work(int u){ 92 while(u){ 93 int v=top[u]; 94 updata(1,n,1,dfn[v],dfn[u],1); 95 u=fa[v]; 96 } 97 } 98 ll _work(int u){ 99 ll ans=0; 100 while(u){ 101 int v=top[u]; 102 ans+=query(1,n,1,dfn[v],dfn[u]); 103 u=fa[v]; 104 } 105 return ans; 106 } 107 int main(){ 108 memset(son,-1,sizeof(son)); 109 memset(head,-1,sizeof(head)); 110 scanf("%d%d",&n,&qq); 111 for(int i=1;i<n;i++){ 112 scanf("%d",&u); 113 add(u+1,i+1); 114 } 115 dfs1(1,0,1); 116 dfs2(1,1); 117 build(1,n,1); 118 for(int i=1;i<=qq;i++){ 119 scanf("%d%d%d",&u,&v,&z); 120 u++,v++,z++; 121 q[++qqq]=(task){u-1,z,i,-1}; 122 q[++qqq]=(task){v,z,i,1}; 123 } 124 sort(q+1,q+qqq+1,cmp); 125 for(int i=1;i<=qqq;i++){ 126 while(tmp<q[i].r){ 127 work(++tmp); 128 } 129 ans[q[i].id]+=(ll)q[i].ok*_work(q[i].z); 130 } 131 for(int i=1;i<=qq;i++){ 132 printf("%lld\n",ans[i]%mod); 133 } 134 return 0; 135 }
转载于:https://www.cnblogs.com/dcdcbigbig/p/9268231.html
【LNOI2014】【BZOJ3626】NOIp2018模拟(三) LCA相关推荐
- 备战Noip2018模拟赛5(B组)T2 Tree 采果子
10月4日备战Noip2018模拟赛5(B组) T2 Tree采果子 题目描述 LYL大牛今天心情不错,于是走到埃及郊外旅游.他边走边向四周望望,发现周围有许多果树.这些树之间互相到达的时间LYL是知 ...
- jzoj 5906. 【NOIP2018模拟10.15】传送门(树形dp)
5906. [NOIP2018模拟10.15]传送门 Description 8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪.但GLaDOS想把传送枪据为己有,于是把Normal ...
- 备战Noip2018模拟赛10(B组) T1 Max 和最大
10月20日备战Noip2018模拟赛10 T1 Max和最大 题目描述 CYF的黑题,偏题,怪题,黑科技题,大码农题都做腻了,于是她想做一下签到水题,她希望从有一个长度为ň的整数序列(A1,A2,. ...
- jzoj5904. 【NOIP2018模拟10.15】刺客信条(并查集)
5904. [NOIP2018模拟10.15]刺客信条 Description 故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一 ...
- 模拟三:STEMA 考试选择题模拟练习试卷(初级组)及答案 + 自我解题笔记
模拟一:STEMA 考试选择题模拟练习试卷(初级组)及答案 + 自我解题笔记 模拟二:STEMA 考试选择题模拟练习试卷(中级组)及答案 + 解题后期更新 模拟三:STEMA 考试选择题模拟练习试卷( ...
- 在Unity中实现基于粒子的水模拟(三:混合屏幕)
在Unity中实现基于粒子的水模拟(三:混合屏幕) 文章目录 在Unity中实现基于粒子的水模拟(三:混合屏幕) 前言 一.着色算法介绍 1.折射 2.反射 二.准备纹理 1.获取纹理 2.模糊纹理 ...
- 备战Noip2018模拟赛3(B组)T1 Apple 韬韬抢苹果
10月3日备战Noip2018模拟赛3(B组) T1 Apple韬韬抢苹果 题目描述 又到了收获的季节,树上结了许多韬韬,错了,是许多苹果,有很多个小韬韬都来摘苹果.每个韬韬都想要最大的苹果,所以发生 ...
- 数组变换-Java-牛客模拟三
package 模拟三;import java.util.Scanner;/*** 题目描述:牛牛有一个数组,里面的数可能不相等,现在他想把数组变为:所有的数都相等.问是否可行.* 牛牛可以进行的操作 ...
- 备战Noip2018模拟赛3(B组) T2 Dance 开场舞蹈
10月3日备战Noip2018模拟赛3(B组) T2 Dance 开场舞蹈 题目描述 在全世界人民的期盼下,2008年北京奥林匹克运动会终于隆重召开了! 为了展示中华民族博大精深的优秀传统文化,负责开 ...
最新文章
- java读取ppt内容_Java 读取/获取PPT文本
- 在WinForm中使用Web Services 来实现软件自动升级(转)
- a.out、coff、elf三种文件格式
- ZYNQ学习心得梳理(一)
- leetcode-Basic Calculator-224
- 字符串匹配算法——KMP算法学习
- Java 反射:Classes
- java工程师认证_Java工程师认证工信部考试.doc
- python3魔法方法_Python3 魔法方法详解
- Flutter Image 参数详解
- 定时任务管理系统(spring boot + quartz + angular)
- 砍价永远差一刀?拼多多法庭上回复:小数点后有6位......
- php if相关标签,dedecms模板中运用dede标签时使用php和if判断语句的方法
- python一键合并上千个Excel表(对不起!!因为这事,我和同事吵了一架)
- 问题记录:系统还原后,QQ显示一直登录中,但却登录不上去,而且很多软件无法使用
- WIN10打开网络共享文件夹提示0x80004005怎么解决?(转载)
- 银行数字化转型导师坚鹏:金融科技与数字化转型成功案例
- java向微信公众号---发送模板和图文消息
- Big Data大数据基础知识
- 什么是循环依赖以及解决方式
热门文章
- Jquery中的hover()和toggle()用法
- PyQt5 图形界面 - Qt Designer设置简体中文方法演示,Qt Designer字体设置,Qt Designer工具单独安装包获取,Qt Designer简体中文语言包获取
- chrome 技术篇-控制台切换框架,切换dom操作区
- [YTU]_2474( C++习题 输入输出--保护继承)
- [YTU]_2617(B C++时间类的运算符重载)
- Python剑指offer:数组中重复的数字
- Vscode配置C语言问题
- 使用canvas实现360水球波动
- MySQL之SQL优化详解(二)
- Use Ghidra To Reverse GenyMotion—Suggestion