思路转化很巧妙。

首先把询问做差分。

然后发现加入一个点就把路径上的点都+1,询问的时候直接询问到根的路径和。

这样和原问题是等价的,然后树链剖分+线段树就可以做了。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair
#define md 201314
#define maxn 100005 int n,q,dep[maxn],data[maxn],ans[maxn]; namespace SegTree{
int sum[maxn<<3],dsum[maxn<<3],tag[maxn<<3];
void update(int o)
{
sum[o]=(sum[o<<1]+sum[o<<1|1])%md;
}
void build(int o,int l,int r)
{
if (l==r)
{
sum[o]=tag[o]=0;
return ;
}
int mid=l+r>>1;
build(o<<1,l,mid); build(o<<1|1,mid+1,r);
update(o);
}
void pushdown(int o,int l,int r)
{
if (tag[o]!=0)
{
int mid=l+r>>1;
tag[o<<1]+=tag[o];tag[o<<1|1]+=tag[o];
sum[o<<1]+=tag[o]*(mid-l+1);
sum[o<<1|1]+=tag[o]*(r-mid);
tag[o]=0;
}
}
int querysum(int o,int l,int r,int L,int R)
{
if (L<=l&&r<=R) return sum[o];
pushdown(o,l,r);
int mid=l+r>>1;
if (R<=mid) return querysum(o<<1,l,mid,L,R);
else if (L>mid) return querysum(o<<1|1,mid+1,r,L,R);
else return (querysum(o<<1,l,mid,L,R)+querysum(o<<1|1,mid+1,r,L,R))%md;
}
void modify(int o,int l,int r,int L,int R,int f)
{
if (L<=l&&r<=R)
{
sum[o]+=(r-l+1)*f;
tag[o]+=f;
return ;
}
pushdown(o,l,r);
int mid=l+r>>1;
if (R<=mid) return modify(o<<1,l,mid,L,R,f),update(o);
else if (L>mid) return modify(o<<1|1,mid+1,r,L,R,f),update(o);
else return modify(o<<1,l,mid,L,R,f),modify(o<<1|1,mid+1,r,L,R,f),update(o);
}
} namespace Tree{
int h[maxn],to[maxn],ne[maxn],en=0;
int siz[maxn],son[maxn],dfn[maxn],top[maxn],fa[maxn],tot;
int pos[maxn],id[maxn];
vector < pair<int,int> > v[maxn];
void add(int a,int b)
{
to[en]=b;ne[en]=h[a];h[a]=en++;
}
void dfs1(int o)
{
siz[o]=1;
for (int i=h[o];i>=0;i=ne[i])
{
dep[to[i]]=dep[o]+1;
fa[to[i]]=o;
dfs1(to[i]);
siz[o]+=siz[to[i]];
if (siz[to[i]]>siz[son[o]]) son[o]=to[i];
}
}
void dfs2(int o,int tp)
{
top[o]=tp;pos[o]=++tot;id[tot]=o;
if (!son[o]) return;
dfs2(son[o],tp);
for (int i=h[o];i>=0;i=ne[i])
if (to[i]!=son[o]) dfs2(to[i],to[i]);
return ;
}
void build()
{
F(i,1,n) data[i]=dep[id[i]];
SegTree::build(1,1,n);
}
void add(int a,int b,int f)
{
while (top[a]!=top[b])
{
if (dep[top[a]]<dep[top[b]]) swap(a,b);
SegTree::modify(1,1,n,pos[top[a]],pos[a],f);
a=fa[top[a]];
}
if (dep[a]<dep[b]) swap(a,b);
SegTree::modify(1,1,n,pos[b],pos[a],f);
}
int query(int a,int b)
{
int ret=0;
while (top[a]!=top[b])
{
if (dep[top[a]]<dep[top[b]]) swap(a,b);
ret+=SegTree::querysum(1,1,n,pos[top[a]],pos[a]);
ret%=md;
a=fa[top[a]];
}
if (dep[a]<dep[b]) swap(a,b);
ret+=SegTree::querysum(1,1,n,pos[b],pos[a]);
return ret%md;
}
void work()
{
F(i,1,q)
{
int l,r,z; scanf("%d%d%d",&l,&r,&z);l++;r++;z++;
v[l-1].push_back(mp(z,-i));
v[r].push_back(mp(z,i));
}
F(i,1,n)
{
add(1,i,1);
for (int j=0;j<v[i].size();++j)
{
pair<int,int> pa=v[i][j];
if (pa.second<0) ans[-pa.second]-=query(1,pa.first);
else ans[pa.second]+=query(1,pa.first);
}
}
F(i,1,q) printf("%d\n",(ans[i]+md)%md);
}
} namespace Graph{
int h[maxn],to[maxn],ne[maxn],en=0;
void add(int a,int b)
{to[en]=b;ne[en]=h[a];h[a]=en++;}
void dfs(int o,int fa)
{
if (fa) Tree::add(fa,o);
for (int i=h[o];i>=0;i=ne[i])
if (to[i]!=fa) dfs(to[i],o);
}
} int main()
{
scanf("%d%d",&n,&q);
memset(Tree::h,-1,sizeof Tree::h);
memset(Graph::h,-1,sizeof Graph::h);
F(i,2,n)
{
int fa; scanf("%d",&fa);
Graph::add(fa+1,i);
}
Graph::dfs(1,0);
dep[1]=1;
Tree::dfs1(1);
Tree::dfs2(1,1);
Tree::build();
Tree::work();
}

  

BZOJ 3626 [LNOI2014]LCA ——树链剖分的更多相关文章

  1. BZOJ 3626: [LNOI2014]LCA 树链剖分 线段树 离线

    http://www.lydsy.com/JudgeOnline/problem.php?id=3626 LNOI的树链剖分题没有HAOI那么水,学到的东西还是很多的. 我如果现场写,很难想出来这种题 ...

  2. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  3. BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )

    说多了都是泪啊...调了这么久.. 离线可以搞 , 树链剖分就OK了... -------------------------------------------------------------- ...

  4. bzoj 3626 : [LNOI2014]LCA (树链剖分+线段树)

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

  5. [BZOJ3626] [LNOI2014]LCA(树链剖分)

    [BZOJ3626] [LNOI2014]LCA(树链剖分) 题面 给出一棵N个点的树,要求支持Q次询问,每次询问一个点z与编号为区间[l,r]内的点分别求最近公共祖先得到的最近公共祖先深度和.N, ...

  6. BZOJ3626[LNOI2014]LCA——树链剖分+线段树

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

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

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

  8. bzoj3626 [LNOI2014]LCA——树链剖分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3626 思路很巧妙,把区间换成前缀和相减: 把 l ~ r 到根路径上的点的点权都+1,然后 ...

  9. [LNOI2014]LCA(树链剖分)

    BZOJ传送门 Luogu传送门 题目:给你一棵树,给你n个询问,每个询问要求输出$\sum_{i=l}^{r}depth(LCA(i,z))$ 细看看其实没有想象的那么难 大体思路: 1.对于每个询 ...

随机推荐

  1. MySQL安装未响应解决方法

    安装MySQL出示未响应,一般显示在安装MySQL程序最后2步的3,4项就不动了. 这种情况一般是你以前安装过MySQL数据库服务项被占用了. 1.卸载MySQL 2.删除安装目录及数据存放目录 3. ...

  2. [论文理解] MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications

    MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications Intro MobileNet 我 ...

  3. 使用Timer组件实现人物动画效果

    实现效果: 知识运用: Graphics类的DrawImage方法 //在指定位置 按原始大小绘制指定的Image对象 public void DrawImage(Image image,Point ...

  4. stack与heap、new的内存分配、static对象。(effective c++ 04)

    阅读effective c++ 04 (30页) 提到的static对象和堆与栈对象."不同编译单元内定义的non-local static对象". 了解一下.    目录 sta ...

  5. Java中将字符串与unicode的相互转换工具类

    unicode编码规则 unicode码对每一个字符用4位16进制数表示.具体规则是:将一个字符(char)的高8位与低8位分别取出,转化为16进制数,如果转化的16进制数的长度不足2位,则在其后补0 ...

  6. nginx url rewrite break和last的区别

    break 将重写的URI作为一个新的URI,在本块中继续处理,将重写后 的地址在当前location块中处理,不会将新的URI转向到其他location块中 last,终止继续在本location块 ...

  7. python3  循环输出当前时间。

    题目 暂停一秒输出(使用 time 模块的 sleep() 函数).循环输出当前时间. 代码: import time while True: time.sleep(1) print(time.str ...

  8. COMP9021--6.13

    1. break语句和continue语句都可以在循环中使用,且常与选择结构结合使用,以达到在特定条件满足时跳出循环的作用.break语句被执行,可以使整个循环提前结束.而continue语句的作用是 ...

  9. day24 02 单继承(派生)

    day24 02 单继承(派生) 1.首先来看一个简单的例子 比如: 狗类的属性有:吃,喝,看门 鸟类的属性有:吃,喝,下蛋 看门和下蛋就是这两种动物不同的属性,而吃喝是两个共同的属性 以下代码实现了 ...

  10. Hessian知识学习总结(二)——Hessian的helloworld

    一.下载Hessian 可在hessian官网http://hessian.caucho.com/ 或者http://download.csdn.net/detail/wodediqizhang/95 ...