bzoj 3626 : [LNOI2014]LCA (树链剖分+线段树)
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
清华爷gconeice的题解:
显然,暴力求解的复杂度是无法承受的。
考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案。观察到,深度其实就是上面有几个已标记了的点(包括自身)。所以,我们不妨把 z 到根的路径上的点全部 +1,对于 l 到 r 之间的点询问他们到根路径上的点权和。仔细观察上面的暴力不难发现,实际上这个操作具有叠加性,且可逆。也就是说我们可以对于 l 到 r 之间的点 i,将 i 到根的路径上的点全部 +1, 转而询问 z 到根的路径上的点(包括自身)的权值和就是这个询问的答案。把询问差分下,也就是用 [1, r] − [1, l − 1] 来计算答案,那么现在我们就有一个明显的解法。从 0 到 n − 1 依次插入点 i,即将 i 到根的路径上的点全部+1。离线询问答案即可。我们现在需要一个数据结构来维护路径加和路径求和,显然树链剖分或LCT 均可以完成这个任务。树链剖分的复杂度为 O((n + q)· log n · log n),LCT的复杂度为 O((n + q)· log n),均可以完成任务。至此,题目已经被我们完美解决。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
const int mod = ;
const int M = 1e5 + ;
struct node{
int to,next;
}e[M];
int cnt,cnt1,n;
int son[M],siz[M],head[M],fa[M],top[M],dep[M],tid[M];
int sum[M<<],lazy[M<<];
void add(int u,int v){
e[++cnt].to = v;e[cnt].next = head[u];head[u] = cnt;
} void dfs1(int u,int faz,int deep){
dep[u] = deep;
fa[u] = faz;
siz[u] = ;
for(int i = head[u];i;i = e[i].next){
int v = e[i].to;
if(v == faz) continue;
dfs1(v,u,deep+);
siz[u] += siz[v];
if(siz[v] > siz[son[u]]||son[u] == -)
son[u] = v;
}
} void dfs2(int u,int t){
top[u] = t;
tid[u] = ++cnt1;
if(son[u] == -) return ;
dfs2(son[u],t);
for(int i = head[u];i;i=e[i].next){
int v = e[i].to;
if(v != fa[u]&&v != son[u])
dfs2(v,v);
}
} void pushup(int rt){
sum[rt] = sum[rt<<] + sum[rt<<|];
} void pushdown(int l,int r,int rt){
if(lazy[rt]){
mid;
sum[rt<<] += (m-l+)*lazy[rt];
sum[rt<<|] += (r-m)*lazy[rt];
lazy[rt<<] += lazy[rt];
lazy[rt<<|] += lazy[rt];
lazy[rt] = ;
}
} void build(int l,int r,int rt){
lazy[rt] = ;
if(l==r){
sum[rt] = lazy[rt] = ;
return ;
}
mid;
build(lson); build(rson);
pushup(rt);
} void update(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
sum[rt] += (r-l+);
lazy[rt] += ;
return ;
}
pushdown(l,r,rt);
mid;
if(L <= m) update(L,R,lson);
if(R > m) update(L,R,rson);
pushup(rt);
} int query(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
return sum[rt];
}
pushdown(l,r,rt);
mid;
int ret = ;
if(L <= m) ret += query(L,R,lson);
if(R > m) ret += query(L,R,rson);
return ret;
} void update(int x,int y){
int fx = top[x],fy = top[y];
while(fx != fy){
if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
update(tid[fx],tid[x],,n,);
x = fa[fx]; fx = top[x];
}
if(dep[x] > dep[y]) swap(x,y);
update(tid[x],tid[y],,n,);
} int solve(int x,int y){
int fx = top[x],fy = top[y];
int ans = ;
while(fx != fy){
if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
ans += query(tid[fx],tid[x],,n,);
x = fa[fx]; fx = top[x];
}
if(dep[x] > dep[y]) swap(x,y);
ans += query(tid[x],tid[y],,n,);
return ans;
}
struct node1{
int ans1,ans2,z;
}q[M];
struct node2{
int pos,flag,id;
}a[M];
bool cmp(node2 x,node2 y){
return x.pos < y.pos;
} int main()
{
int m,l,r,x;
cnt = ;cnt1 = ;
scanf("%d%d",&n,&m);
for(int i = ;i < n;i ++){
scanf("%d",&x);
add(x+,i+);
}
memset(son,-,sizeof(son));
dfs1(,,); dfs2(,);
build(,n,);
int tot = ;
for(int i = ;i <= m;i ++){
scanf("%d%d%d",&l,&r,&q[i].z);
l++;r++;q[i].z++;
a[++tot].pos=l-;a[tot].flag=;a[tot].id=i;
a[++tot].pos=r;a[tot].flag=;a[tot].id=i;
}
int now = ;
sort(a+,a+tot+,cmp);
for(int i = ;i <= tot;i ++){
while(now <= a[i].pos){
update(,now);
now++;
}
int num = a[i].id;
if(a[i].flag==) q[num].ans1 = solve(,q[num].z);
else q[num].ans2 = solve(,q[num].z);
}
for(int i = ;i <= m;i ++){
int ans = (q[i].ans2-q[i].ans1)%mod;
printf("%d\n",ans);
}
return ;
}
bzoj 3626 : [LNOI2014]LCA (树链剖分+线段树)的更多相关文章
- 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树
题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2852 Solved: 1668[Submit][Sta ...
- bzoj 2157: 旅游【树链剖分+线段树】
裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...
- BZOJ 3589 动态树 (树链剖分+线段树)
前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
随机推荐
- 常用yum操作命令
1.yum repolist 获取当前系统有效的repolist,如下图 2.yum list,列出所有可安装的软件包 获取当前有效repolist中所能安装的所有rpm包列表,(很长,慎重),可以结 ...
- centos7 安装phpmyadmin
1.先安装epel,不然安装pgpmyadmin时会出现找不到包. yum install epel-release rpm -ivh http://rpms.famillecollet.com/en ...
- MySql实现分页查询的SQL,mysql实现分页查询的sql语句
一:分页需求: 客户端通过传递start(页码),limit(每页显示的条数)两个参数去分页查询数据库表中的数据,那我们知道MySql数据库提供了分页的函数limit m,n,但是该函数的用法和我们的 ...
- Linux之查看系统配置命令
1.查看CPU个数: [root@ifusion ~]# lscpu 2.查看CPU进程数.核数: [root@ifusion ~]# cat /proc/cpuinfo 3.查看内存总量: [roo ...
- 监控系统对比 Ganglia vs Open-falcon vs Prometheus vs Zabbix vs Nagios vs PandoraFMS
Zabbix vs Nagios vs PandoraFMS: an in depth comparison - Pandora FMS - The Monitoring Bloghttps://bl ...
- IdentityServer4【Introduction】之术语
术语 在规范.文档和对象模型中使用了一些你应该了解的术语. IdentityServer IdentityServer是一个OpenID Connect的提供者,它实现了OpenID Connect和 ...
- HashMap深度解析(转载)
原文地址:http://blog.csdn.net/ghsau/article/details/16890151 实现原理:用一个数组来存储元素,但是这个数组存储的不是基本数据类型.HashMap实现 ...
- png8、16、24、32位的区别
我们都知道一张图片可以保存为很多种不同的格式,比如bmp/png/jpeg/gif等等.这个是从文件格式的角度看,我们抛开文件格式,看图片本身,我们可以分为8位, 16位, 24位, 32位等. 单击 ...
- drf 之序列化组件
序列化 把Python中对象转换为json格式字符串 反序列化 把json格式转为为Python对象. 用orm查回来的数据都是都是一个一个的对象, 但是前端要的是json格式字符串. 序列化两大功能 ...
- Codeforces 1154F Shovels Shop
题目链接:http://codeforces.com/problemset/problem/1154/F 题目大意: 商店有n把铲子,欲购k把,现有m种优惠,每种优惠可使用多次,每种优惠(x, y)表 ...