【BZOJ3626】[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

5 2
0
0
1
1
1 4 3
1 4 2

Sample Output

8
5

HINT

共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。

题解:考虑dep[lca(a,b)]可以表示成什么,我们将a到根路径上的每个节点的权值都+1,然后查询b到根的路径上的所有点的权值和即可。

发现这个东西是可以用前缀和来搞的。我们将询问拆成前缀相减的形式,从1到n枚举i,将i到根路径上所有点的权值和+1,顺便处理当前的所有询问即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mod 201314
#define lson x<<1
#define rson x<<1|1
using namespace std;
const int maxn=50010;
int n,m,sum,tot,cnt;
int to[maxn],next[maxn],head[maxn],deep[maxn],siz[maxn],fa[maxn],top[maxn],son[maxn],p[maxn];
int s[maxn<<2],t[maxn<<2],ans[maxn];
struct QUERY
{
int qx,org,k,qz;
}q[maxn<<1];
inline int rd()
{
int ret=0; char gc=getchar();
while(gc<'0'||gc>'9') gc=getchar();
while(gc>='0'&&gc<='9') ret=(ret<<3)+(ret<<1)+gc-'0',gc=getchar();
return ret;
}
bool cmp(QUERY a,QUERY b)
{
return a.qx<b.qx;
}
void dfs1(int x)
{
siz[x]=1;
for(int i=head[x];i!=-1;i=next[i])
{
deep[to[i]]=deep[x]+1;
dfs1(to[i]);
siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[son[x]]) son[x]=to[i];
}
}
void dfs2(int x,int tp)
{
top[x]=tp,p[x]=++tot;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=son[x]) dfs2(to[i],to[i]);
}
void pushdown(int l,int r,int x)
{
if(t[x])
{
int mid=(l+r)>>1;
s[lson]=(s[lson]+(mid-l+1)*t[x])%mod;
s[rson]=(s[rson]+(r-mid)*t[x])%mod;
t[lson]+=t[x],t[rson]+=t[x],t[x]=0;
}
}
void updata(int l,int r,int x,int a,int b)
{
if(a<=l&&r<=b)
{
s[x]+=r-l+1,t[x]++;
return ;
}
pushdown(l,r,x);
int mid=(l+r)>>1;
if(a<=mid) updata(l,mid,lson,a,b);
if(b>mid) updata(mid+1,r,rson,a,b);
s[x]=(s[lson]+s[rson])%mod;
}
int query(int l,int r,int x,int a,int b)
{
if(a<=l&&r<=b) return s[x];
pushdown(l,r,x);
int mid=(l+r)>>1;
if(b<=mid) return query(l,mid,lson,a,b);
if(a>mid) return query(mid+1,r,rson,a,b);
return query(l,mid,lson,a,b)+query(mid+1,r,rson,a,b);
}
void insert(int x)
{
while(x) updata(1,n,1,p[top[x]],p[x]),x=fa[top[x]];
}
int getsum(int x)
{
int ret=0;
while(x) ret=(ret+query(1,n,1,p[top[x]],p[x]))%mod,x=fa[top[x]];
return ret;
}
void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
int main()
{
n=rd(),m=rd();
int i,j;
memset(head,-1,sizeof(head));
for(i=2;i<=n;i++) fa[i]=rd()+1,add(fa[i],i);
deep[1]=1;
dfs1(1),dfs2(1,1);
for(i=1;i<=m;i++)
{
q[i*2-1].qx=rd(),q[i*2].qx=rd()+1;
q[i*2-1].qz=q[i*2].qz=rd()+1;
q[i*2-1].k=-1,q[i*2].k=1;
q[i*2-1].org=q[i*2].org=i;
}
sort(q+1,q+2*m+1,cmp);
for(i=1;i<=2*m;i++)
{
for(j=q[i-1].qx+1;j<=q[i].qx;j++) insert(j);
ans[q[i].org]+=q[i].k*getsum(q[i].qz);
}
for(i=1;i<=m;i++) printf("%d\n",(ans[i]+mod)%mod);
return 0;
}

【BZOJ3626】[LNOI2014]LCA 离线+树链剖分+线段树的更多相关文章

  1. 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树

    题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...

  2. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  3. 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 ...

  4. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

  5. 2019西北工业大学程序设计创新实践基地春季选拔赛 I Chino with Rewrite (并查集+树链剖分+线段树)

    链接:https://ac.nowcoder.com/acm/contest/553/I 思路:离线整棵树,用并查集维护下联通的情况,因为值只有60个,用2的x(1<=x<=60)次方表示 ...

  6. 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树

    正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...

  7. BZOJ3862Little Devil I——树链剖分+线段树

    题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...

  8. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树

    题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...

  9. BZOJ2819Nim——树链剖分+线段树+Nim游戏

    题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...

  10. POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...

随机推荐

  1. [显示属性]-自定义桌面里没有IE选项

    1楼 哈哈,我来告诉你原因,微软为了应对欧盟的反垄断调查,在 SP3 的“自定义桌面”里去掉了 Internet Explorer 选项. 如果桌面 IE 图标被误删除,但是又想恢复,而不是建立快捷方 ...

  2. firefox浏览器批处理插件imacros

    http://www.360doc.com/content/14/1012/19/4360822_416372016.shtml javascript部分 var code = "CODE: ...

  3. Hive 中的变量

    Hive的变量前面有一个命名空间,包括三个hiveconf,system,env,还有一个hivevar hiveconf的命名空间指的是hive-site.xml下面的配置变量值. system的命 ...

  4. 公众号的TOKEN配置PHP代码

    1.在后台添加好URL和TOKEN和生成43位随机码  注意域名URL需要备案 2.上传到服务器 3.公众号后台要点提交即可 error_reporting(0); $signature=$_REQU ...

  5. iframe自适应高度处理

    一中方法: 在子页面加载完毕的时候执行 parent.document.getElementById("iframe").height=0; parent.document.get ...

  6. redis基础之安装和配置(一)

    前言 折腾一下redis在linux环境的安装. ubantu16.04环境下安装 下载安装,依次执行命令; # 从官方网站下载安装包,注意,当前在哪个目录下执行命令,下载的包将在哪个目录下 $ wg ...

  7. Windows版变色龙

    打包安装版本更新源地址: http://www.insanelymac.com/forum/files/file/59-chameleon-22-svn/ 一.使用方法:1.安装Windows版变色龙 ...

  8. js delete

    在开始之前,先让我们看一段代码 >>> var sum = function(a, b) {return a + b;} >>> var add = sum; &g ...

  9. java服务端json结果集传值给前端的数据输出格式

    在服务端输出json数据时按照一定的格式输出时间字段,fastjson支持两种方式:1.使用JSON.toJSONStringWithDateFormat方法2.JSON.toJSONString方法 ...

  10. C++中变量做数组长度

    在Java中,这是完全可以的,比如我们运行如下程序: package cn.darrenchan.storm; import java.util.Arrays; public class Test { ...