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相关推荐

  1. 备战Noip2018模拟赛5(B组)T2 Tree 采果子

    10月4日备战Noip2018模拟赛5(B组) T2 Tree采果子 题目描述 LYL大牛今天心情不错,于是走到埃及郊外旅游.他边走边向四周望望,发现周围有许多果树.这些树之间互相到达的时间LYL是知 ...

  2. jzoj 5906. 【NOIP2018模拟10.15】传送门(树形dp)

    5906. [NOIP2018模拟10.15]传送门 Description 8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪.但GLaDOS想把传送枪据为己有,于是把Normal ...

  3. 备战Noip2018模拟赛10(B组) T1 Max 和最大

    10月20日备战Noip2018模拟赛10 T1 Max和最大 题目描述 CYF的黑题,偏题,怪题,黑科技题,大码农题都做腻了,于是她想做一下签到水题,她希望从有一个长度为ň的整数序列(A1,A2,. ...

  4. jzoj5904. 【NOIP2018模拟10.15】刺客信条(并查集)

    5904. [NOIP2018模拟10.15]刺客信条 Description 故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一 ...

  5. 模拟三:STEMA 考试选择题模拟练习试卷(初级组)及答案 + 自我解题笔记

    模拟一:STEMA 考试选择题模拟练习试卷(初级组)及答案 + 自我解题笔记 模拟二:STEMA 考试选择题模拟练习试卷(中级组)及答案 + 解题后期更新 模拟三:STEMA 考试选择题模拟练习试卷( ...

  6. 在Unity中实现基于粒子的水模拟(三:混合屏幕)

    在Unity中实现基于粒子的水模拟(三:混合屏幕) 文章目录 在Unity中实现基于粒子的水模拟(三:混合屏幕) 前言 一.着色算法介绍 1.折射 2.反射 二.准备纹理 1.获取纹理 2.模糊纹理 ...

  7. 备战Noip2018模拟赛3(B组)T1 Apple 韬韬抢苹果

    10月3日备战Noip2018模拟赛3(B组) T1 Apple韬韬抢苹果 题目描述 又到了收获的季节,树上结了许多韬韬,错了,是许多苹果,有很多个小韬韬都来摘苹果.每个韬韬都想要最大的苹果,所以发生 ...

  8. 数组变换-Java-牛客模拟三

    package 模拟三;import java.util.Scanner;/*** 题目描述:牛牛有一个数组,里面的数可能不相等,现在他想把数组变为:所有的数都相等.问是否可行.* 牛牛可以进行的操作 ...

  9. 备战Noip2018模拟赛3(B组) T2 Dance 开场舞蹈

    10月3日备战Noip2018模拟赛3(B组) T2 Dance 开场舞蹈 题目描述 在全世界人民的期盼下,2008年北京奥林匹克运动会终于隆重召开了! 为了展示中华民族博大精深的优秀传统文化,负责开 ...

最新文章

  1. java读取ppt内容_Java 读取/获取PPT文本
  2. 在WinForm中使用Web Services 来实现软件自动升级(转)
  3. a.out、coff、elf三种文件格式
  4. ZYNQ学习心得梳理(一)
  5. leetcode-Basic Calculator-224
  6. 字符串匹配算法——KMP算法学习
  7. Java 反射:Classes
  8. java工程师认证_Java工程师认证工信部考试.doc
  9. python3魔法方法_Python3 魔法方法详解
  10. Flutter Image 参数详解
  11. 定时任务管理系统(spring boot + quartz + angular)
  12. 砍价永远差一刀?拼多多法庭上回复:小数点后有6位......
  13. php if相关标签,dedecms模板中运用dede标签时使用php和if判断语句的方法
  14. python一键合并上千个Excel表(对不起!!因为这事,我和同事吵了一架)
  15. 问题记录:系统还原后,QQ显示一直登录中,但却登录不上去,而且很多软件无法使用
  16. WIN10打开网络共享文件夹提示0x80004005怎么解决?(转载)
  17. 银行数字化转型导师坚鹏:金融科技与数字化转型成功案例
  18. java向微信公众号---发送模板和图文消息
  19. Big Data大数据基础知识
  20. 什么是循环依赖以及解决方式

热门文章

  1. Jquery中的hover()和toggle()用法
  2. PyQt5 图形界面 - Qt Designer设置简体中文方法演示,Qt Designer字体设置,Qt Designer工具单独安装包获取,Qt Designer简体中文语言包获取
  3. chrome 技术篇-控制台切换框架,切换dom操作区
  4. [YTU]_2474( C++习题 输入输出--保护继承)
  5. [YTU]_2617(B C++时间类的运算符重载)
  6. Python剑指offer:数组中重复的数字
  7. Vscode配置C语言问题
  8. 使用canvas实现360水球波动
  9. MySQL之SQL优化详解(二)
  10. Use Ghidra To Reverse GenyMotion—Suggestion