题目戳我

\(\text{Solution:}\)

这题的转化思想很巧妙……

考虑把\(dep\)给拆掉。

首先可以明确的是,每一个\(LCA\)一定在\(root\to z\)的路径上。

考虑一个\(LCA\)被选中,意味\(root\to LCA\)这个路径上所有的值都\(+1\).

于是,我们可以把询问看成将点\(p\in [l,r],add(root\to p,1)\)并从\(z\)向根的路径上求和即可。

这个区间修改,区间查询显然的树剖线段树板子。而若对于每一个询问都做一次,复杂度显然不够。

考虑将询问离线。

将一个区间询问\([l,r]\)拆成区间\([l,l-1] and [1,r]\)并用差分的思想进行处理。于是,对每一个拆开的区间按照右端点排序(因为左端点都是\(1\))进行离线处理即可,这样就避免了每一次的清空操作。

总结:对于一个\(dep\)的询问,我们可以看成:

  • 从\(i\)向根的路径上进行区间\(+1\).

  • 从\(z\)向根的路径上进行区间求和。

这样,我们可以巧妙地通过区间加来规避对\(dep\)的询问。

笔者一开始硬挖掘编号连续的性质往线段树维护深度和的歪路上走了很久……一度自闭

值得记录的好题。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN=5e5+10;
const int mod=201314;
int dep[MAXN],siz[MAXN],top[MAXN],head[MAXN],rt;
int tot,cnt,n,m,rk[MAXN],id[MAXN],dfstime,ls[MAXN];
int rs[MAXN],pa[MAXN],son[MAXN],qcnt,Ans[MAXN];
struct E{int nxt,to;}e[MAXN];
inline void link(int x,int y){e[++tot]=(E){head[x],y};head[x]=tot;}
inline int add(int x,int y){return (x+y)%mod;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
struct SGT{int l,r,sum,tag;}tr[MAXN];
inline void pushup(int x){tr[x].sum=tr[ls[x]].sum+tr[rs[x]].sum;}
inline int LL(int x){return tr[x].r-tr[x].l+1;}
inline void pushdown(int x){
if(tr[x].tag){
int p=tr[x].tag;tr[x].tag=0;
tr[ls[x]].tag+=p;tr[rs[x]].tag+=p;
tr[ls[x]].tag%=mod;tr[rs[x]].tag%=mod;
tr[ls[x]].sum=add(tr[ls[x]].sum,mul(LL(ls[x]),p));
tr[rs[x]].sum=add(tr[rs[x]].sum,mul(LL(rs[x]),p));
}
}
void build(int l,int r,int x){
tr[x].l=l,tr[x].r=r;
if(l==r)return;
int mid=(l+r)>>1;
ls[x]=cnt++;rs[x]=cnt++;
build(l,mid,ls[x]);
build(mid+1,r,rs[x]);
pushup(x);
}
void dfs1(int x,int fa){
pa[x]=fa,siz[x]=1,dep[x]=dep[fa]+1;
for(int i=head[x];i;i=e[i].nxt){
int j=e[i].to;
if(j==fa)continue;
dfs1(j,x);siz[x]+=siz[j];
if(siz[j]>siz[son[x]])son[x]=j;
}
}
void dfs2(int x,int t){
top[x]=t,rk[id[x]=++dfstime]=x;
if(!son[x])return;dfs2(son[x],t);
for(int i=head[x];i;i=e[i].nxt){
int j=e[i].to;
if(j!=pa[x]&&j!=son[x])dfs2(j,j);
}
}
void update(int l,int r,int v,int x){
if(tr[x].l>=l&&tr[x].r<=r){
tr[x].tag=add(tr[x].tag,v);
tr[x].sum=add(tr[x].sum,mul(LL(x),v));
return;
}
int mid=(tr[x].l+tr[x].r)>>1;pushdown(x);
if(l<=mid)update(l,r,v,ls[x]);
if(mid<r)update(l,r,v,rs[x]);
pushup(x);
}
int query(int l,int r,int x){
if(tr[x].l>=l&&tr[x].r<=r)return tr[x].sum;
int T=0,mid=(tr[x].l+tr[x].r)>>1;pushdown(x);
if(l<=mid)T=add(T,query(l,r,ls[x]));
if(mid<r)T=add(T,query(l,r,rs[x]));
pushup(x);return T;
}
void updatechain(int x,int y,int v){
while(top[x]!=top[y]){
if(dep[x]<dep[y])swap(x,y);
update(id[top[x]],id[x],v,rt);
x=pa[top[x]];
}
if(id[x]>=id[y])swap(x,y);
update(id[x],id[y],v,rt);
}
int querychain(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(dep[x]<dep[y])swap(x,y);
ans=add(ans,query(id[top[x]],id[x],rt));
x=pa[top[x]];
}
if(id[x]>id[y])swap(x,y);
ans=add(ans,query(id[x],id[y],rt));
return ans;
}
struct Query{int pos,num,fg,z;}q[MAXN];
inline bool cmp(Query A,Query B){return A.pos<B.pos;}
pair<int,int>ans[MAXN];
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=2;i<=n;++i){
int x;
scanf("%lld",&x);
x++;
link(x,i);link(i,x);
}
dfs1(1,0);dfs2(1,1);rt=cnt++;build(1,n,rt);
for(int i=1;i<=m;++i){
int a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
a++,b++,c++;
q[++qcnt]=(Query){a-1,i,0,c};
q[++qcnt]=(Query){b,i,1,c};
}
sort(q+1,q+qcnt+1,cmp);
int now=0;
for(int i=1;i<=qcnt;++i){
while(now<q[i].pos)updatechain(++now,1,1);
if(!q[i].fg)ans[q[i].num].first=querychain(q[i].z,1);
else ans[q[i].num].second=querychain(q[i].z,1);
}
for(int i=1;i<=m;++i)Ans[i]=(ans[i].second-ans[i].first+mod)%mod;
for(int i=1;i<=m;++i)printf("%lld\n",Ans[i]);
return 0;
}

【题解】[LNOI2014]LCA的更多相关文章

  1. 题解 LNOI2014 LCA

    题目:传送门 这道题根本不用lca,也没有部分分... 考虑求两个点xy的lca的深度. 我们将x到树根所有点的值都加1,然后查询y到根的和,其实就是lca的深度. 所以本题离线一下上树剖乱搞就可以了 ...

  2. 【BZOJ3626】[LNOI2014]LCA 离线+树链剖分+线段树

    [BZOJ3626][LNOI2014]LCA Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度 ...

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

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

  4. bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)

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

  5. bzoj 3626: [LNOI2014]LCA 离线+树链剖分

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

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

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

  7. 洛谷 P4211 [LNOI2014]LCA 解题报告

    [LNOI2014]LCA 题意 给一个\(n(\le 50000)\)节点的有根树,询问\(l,r,z\),求\(\sum_{l\le i\le r}dep[lca(i,z)]\) 一直想启发式合并 ...

  8. P4211 [LNOI2014]LCA

    P4211 [LNOI2014]LCA 链接 分析: 首先一种比较有趣的转化是,将所有点到1的路径上都+1,然后z到1的路径上的和,就是所有答案的deep的和. 对于多次询问,要么考虑有把询问离线,省 ...

  9. P4211 [LNOI2014]LCA LCT

    P4211 [LNOI2014]LCA 链接 loj luogu 思路 多次询问\(\sum\limits_{l \leq i \leq r}dep[LCA(i,z)]\) 可以转化成l到r上的点到根 ...

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

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

随机推荐

  1. Spark保存的时候怎么去掉多余的引号转义

    今天用SparkSQL保存一份json数据的时候,引号被转义了,并用括号包起来了,导致下游新来的小伙伴无法处理这份数据. 保存后的数据长这样(用\t分割): data "{\"ke ...

  2. Apache 软件基金会顶级项目 Pulsar 达成新里程碑:全球贡献者超 300 位!

    各位 Pulsar 社区小伙伴们: 今天我们高兴地宣布Pulsar 达成新里程碑,全球贡献者超 300 位! 距离 Pulsar 实现 200 位贡献者里程碑,仅仅间隔 8 个月! 作为 Apache ...

  3. 攻防世界——web新手练习区解题记录<1>(1-4题)

    web新手练习区一至四题 第一题view_source: 题目说右键不管用了,我们先获取在线场景来看一看,我们看到这样一个网页,并且右键确实点了没什么反应,而用到右键一般就是查看网页源码 用快捷键(F ...

  4. 几个Graphics函数

    1.Graphics.Blit:Copies source texture into destination render texture with a shader 声明: 1.public sta ...

  5. [HGAME] Week1 Web WriteUp

    一 .Cosmos的博客 打开题目之后,首页直接给了我们提示: 版本管理工具常用的有git和svn两种,这里提示了GitHub,考虑Git信息泄露,先访问/.git/目录考虑用Githack获取泄露信 ...

  6. Oracle 回滚段undo

    Undo的作用 数据的回滚 一致性读 表的闪回(事务,查询的闪回..) 失败会话的恢复 回滚rollback操作 SQL> archive log list; ORA-01031: 权限不足 S ...

  7. Mysql慢查询(配置)

    慢查询?什么鬼?查询很慢吗?刚看一脸萌,学无止境 好吧,就是执行很慢的SQL 什么是慢查询 慢查询定义及作用 慢查询日志,顾名思义,就是查询慢的日志(感觉在说F话),是指Mysql记录所有执行超过lo ...

  8. jQuery提供的Ajax方法

    jQuery提供了4个ajax方法:$.get()  $.post()  $.ajax()  $.getJSON() 1.$.get() $.get(var1,var2,var3,var4): 参数1 ...

  9. roarctf_2019_easy_pwn

    这篇博客主要记录当直接在malloc_hook中直接写入one_gadget不起作用时的一些处理方法.题目附件:https://buuoj.cn/challenges#roarctf_2019_eas ...

  10. 为什么选择H5游戏开发定制?

    为什么选择H5游戏开发定制? 随着微信H5游戏推广带来的显著效果,越来越多的商家已经加入到游戏营销的队伍中来, 对H5小游戏有了解的商家都知道,[模板游戏]的价格往往低于[定制游戏]的价格,可是为什么 ...