#HYSBZ3626[LNOI2014]#LCA(经典模型:树剖+线段树维护和)
3626: [LNOI2014]LCA
Time Limit: 10 Sec Memory Limit: 128 MB
Description
给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
(即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)
Input
第一行2个整数n q。
接下来n-1行,分别表示点1到点n-1的父节点编号。
接下来q行,每行3个整数l r z。
Output
输出q行,每行表示一个询问的答案。每个答案对201314取模输出
Sample Input
0
0
1
1
1 4 3
1 4 2
Sample Output
5
HINT
共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。
很经典的树剖题,学会了一种新的方法。
预备一下做法:
对于要求的i, z的LCA的祖先深度,我们可以这样做,首先将从i到根的每个节点都+1,然后统计从z到根的和,和即为深度,如图:
离线询问,将一个询问区间拆成[1, l-1]和[1, r],那么[l, r]的和就变成了sum[1, r] - sum[1, l - 1]
将所有点按照轻重链先后dfs序重编号,那么重链上的点编号一定是连续的,一个点也是重链。
用重新编的号作为线段树的下标。
从1~N每个点暴力向根节点+1,然后每次就统计从z到根的和,就是当时的[1, i]的sum。
加的时候就是按着轻重链剖分的方法,一直tp到根,每一段重链可以直接按照新编号的下标直接在线段树上更新区间。
每次查询也是按着轻重链剖分的方法,一直tp到根,每次询问一段重链的和。
时间复杂度为Nlog^2 N
Code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;const int Max = 50000;
const int MOD = 201314;struct node{int pos, t, id, tg;bool operator < (const node X)const{return pos < X.pos;}
}Ask[(Max << 1) + 5];
struct TREE{int l, r, sum, ad, num;
}Tr[(Max << 2) + 5];int N, Q, ecnt, POS;
int fir[Max + 5], nxt[Max + 5], V[Max + 5], An[(Max << 1) + 5];
int fa[Max + 5], sz[Max + 5], son[Max + 5], tp[Max + 5], Dep[Max + 5];
int ID[Max + 5], P[Max + 5];void getint(int & num){char c; int flg = 1; num = 0;while((c = getchar()) < '0' || c > '9') if(c == '-') flg = -1;while(c >= '0' && c <= '9'){ num = num * 10 + c - 48; c = getchar(); }num *= flg;
}void addedge(int a, int b){V[++ ecnt] = b, nxt[ecnt] = fir[a], fir[a] = ecnt;
}void Dfs1(int u, int ff){Dep[u] = Dep[ff] + 1;sz[u] = 1;for(int i = fir[u]; i; i = nxt[i]){Dfs1(V[i], u), sz[u] += sz[V[i]];if(sz[V[i]] > sz[son[u]]) son[u] = V[i];}
}void Dfs2(int u){ID[u] = ++ POS;P[POS] = u;if(son[u]){tp[son[u]] = tp[u];Dfs2(son[u]);}for(int i = fir[u]; i; i = nxt[i]) if(V[i] != fa[u] && V[i] != son[u])tp[V[i]] = V[i],Dfs2(V[i]);
}void Build(int i, int l, int r){Tr[i].l = l, Tr[i].r = r, Tr[i].sum = Tr[i].ad = 0;if(l == r){Tr[i].num = P[l], Tr[i].sum = 0;return ;}int mid = (l + r) >> 1;Build(i << 1, l, mid);Build(i << 1 | 1, mid + 1, r);Tr[i].sum = (Tr[i << 1].sum + Tr[i << 1 | 1].sum) % MOD;
}void pushdown(int i){int lc = i << 1, rc = i << 1 | 1;Tr[lc].ad = (Tr[lc].ad + Tr[i].ad) % MOD;Tr[rc].ad = (Tr[rc].ad + Tr[i].ad) % MOD;Tr[lc].sum = (Tr[lc].sum + 1ll*Tr[i].ad * (Tr[lc].r - Tr[lc].l + 1) % MOD) % MOD;Tr[rc].sum = (Tr[rc].sum + 1ll*Tr[i].ad * (Tr[rc].r - Tr[rc].l + 1) % MOD) % MOD;Tr[i].ad = 0;
}void Add(int i, int L, int R){if(L <= Tr[i].l && R >= Tr[i].r){Tr[i].ad = (Tr[i].ad + 1) % MOD;Tr[i].sum = (Tr[i].sum + Tr[i].r - Tr[i].l + 1) % MOD;return ;}int mid = (Tr[i].l + Tr[i].r) >> 1;if(Tr[i].ad) pushdown(i);if(L <= mid) Add(i << 1, L, R);if(R > mid) Add(i << 1 | 1, L, R);Tr[i].sum = (Tr[i << 1].sum + Tr[i << 1 | 1].sum) % MOD;
}int Query(int i, int L, int R){if(L <= Tr[i].l && R >= Tr[i].r) return Tr[i].sum;if(Tr[i].ad) pushdown(i);int mid = (Tr[i].l + Tr[i].r) >> 1, rt = 0;if(L <= mid) rt = (rt + Query(i << 1, L, R)) % MOD;if(R > mid) rt = (rt + Query(i << 1 | 1, L, R)) % MOD;Tr[i].sum = (Tr[i << 1].sum + Tr[i << 1 | 1].sum) % MOD;return rt;
}void Update(int u){while(u){Add(1, ID[tp[u]], ID[u]);u = fa[tp[u]];}
}int Cal(int u){int rt = 0;while(u){rt = (rt + Query(1, ID[tp[u]], ID[u])) % MOD;u = fa[tp[u]];}return rt;
}int main(){getint(N), getint(Q);for(int i = 2; i <= N; ++ i)getint(fa[i]), ++ fa[i], addedge(fa[i], i);Dfs1(1, 0);tp[1] = 1;Dfs2(1);Build(1, 1, N);int l, r, T = 0;int R = 0;for(int i = 1; i <= Q; ++ i){getint(l), getint(r), getint(Ask[++ T].t);++ l, ++ r, ++ Ask[T].t;Ask[T].pos = l - 1, Ask[T].id = i, Ask[T].tg = -1, ++ T;Ask[T].t = Ask[T - 1].t, Ask[T].pos = r, Ask[T].id = i, Ask[T].tg = 1;R = max(R, r);}sort(Ask + 1, Ask + 1 + T);int p = 1;for(int i = 1; i <= T; ){while(p <= Ask[i].pos){Update(p), ++ p;}int j;for(j = i; j <= T && Ask[j].pos == Ask[i].pos; ++ j){int tmp = Cal(Ask[j].t);An[Ask[j].id] += Ask[j].tg * tmp ;}i = j;}for(int i = 1; i <= Q; ++ i) printf("%d\n", (An[i] + MOD) % MOD);return 0;
}
/*
5 2
0
0
1
1
1 4 3
1 4 2
7 5
0 0 1 1 2 2
0 6 0
0 6 1
5 6 2
5 6 1
0 4 1
7
10
4
2
8
*/
#HYSBZ3626[LNOI2014]#LCA(经典模型:树剖+线段树维护和)相关推荐
- BZOJ3531-[Sdoi2014]旅行(树剖+线段树动态开点)
传送门 完了今天才知道原来线段树的动态开点和主席树是不一样的啊 我们先考虑没有宗教信仰的限制,那么就是一个很明显的树剖+线段树,路径查询最大值以及路径和 然后有了宗教信仰的限制该怎么做呢? 先考虑暴力 ...
- BZOJ 4817: [Sdoi2017]树点涂色(LCT+树剖+线段树)
题目描述 Bob有一棵 nn 个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. Bob ...
- 树剖+线段树||树链剖分||BZOJ1984||Luogu4315||月下“毛景树”
题面:月下"毛景树" 题解:是道很裸的树剖,但处理的细节有点多(其实是自己线段树没学好).用一个Dfs把边权下移到点权,用E数组记录哪些边被用到了:前三个更新的操作都可以合并起来, ...
- BZOJ4034 树上操作(树剖 线段树大模板)
BZOJ4034 long long 是大坑点 貌似long long 跟int 乘起来会搞事情?... A了这题线段树和树剖的基础OK 嘛 重点过掉的还是线段树区间更新的lazy tag吧 #inc ...
- 2019ICPC西安邀请赛 E. Tree(树剖 + 线段树)
Tree 给定一棵树,节点有点权,然后有三种操作: 一.修改1−>s1->s1−>s的路径上的点权与ttt进行按位或. 二.修改1−>s1->s1−>s的路径上的点 ...
- P3292 [SCOI2016]幸运数字(树剖 + 线段树维护线性基)
P3292 [SCOI2016]幸运数字 思路 如果这题是求x,yx, yx,y之间的距离显然我们可以通过树剖加线段树来写, 但是这里变成了求任意个数的异或最大值.如果给定区间我们显然可以通过线性基来 ...
- ural 1553 树剖+线段树
//链式前向星版 #include<bits/stdc++.h> using namespace std; const int maxn=100010; //建图 int to[maxn* ...
- 2021 Jiangsu Collegiate Programming Contest F. Jumping Monkey II 树剖+线段树
F. Jumping Monkey II 题意: 给你 n = 2 e 5 n=2e5 n=2e5的一棵树,每个点有点权 a [ i ] < = 1 e 9 a[i]<=1e9 a[i]& ...
- 洛谷2543AHOI2005]航线规划 (树剖+线段树+割边思路)
这个题的思路还是比较巧妙的. 首先,我们发现操作只有删除和询问两种,而删除并不好维护连通性和割边之类的信息. 所以我们不妨像WC2006水管局长那样,将询问离线,然后把操作转化成加边和询问. 然后,我 ...
最新文章
- 【C++】 15_类于封装的概念
- Xamarin图表开发基础教程(3)OxyPlot框架
- WF4 持久化 第四篇
- BGP、MPLS是怎么组合到一起的?
- 还在为系统迁移烦恼?掌握这些“基本法”解锁更多可能
- 开发者基础知识游戏,共10关,欢迎挑战
- java 基本语法与流程控制_Java基础语法之控制流程
- 【OS学习笔记】二十八 保护模式八:任务切换对应的汇编代码之内核代码
- 【HDU - 2717】【POJ - 3278】Catch That Cow (经典bfs,类似dp)
- EMC VMAX的磁盘构成,fast policy(重要)
- 网页制作的基本语言html,网页制作基础语言HTML.ppt
- 【转】怎样成为优秀的软件模型设计者(文末提供下载)
- android wifi在待机状态下可用,Android APP休眠状态下无法联网和播放音频解决方案...
- C++——override
- 从72万现金到骨灰盒,还有什么是不能被忘在网约车上的?
- true是不是python保留字_Python基本语法--关键字和保留字篇
- VB模拟键盘输入的N种方法
- 怎么实现角色权限的分配_在 Go 语言中使用 casbin 实现基于角色的 HTTP 权限控制...
- ele input事件 输入后0.5秒触发
- 调整计算机繁体,在线繁体转换