题目大意

有一棵有\(n\)(\(n\leq5*10^4\))个点的树,\(q\)(\(q\leq5*10^4\))次询问,每次给出\(l,r,x\)表示询问所有编号在\([l,r]\)的点与点\(x\)的LCA的深度之和

题解

将\([l,r]\)里每个点和该点的所有祖先点权+1后,查询点\(x\)和它的祖先的点权和就行了

可持久化线段树维护

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];k!=-1;k=nxt[k])
#define maxn 50010
#define ls (son[u][0])
#define rs (son[u][1])
#define lsa son[ua][0]
#define rsa son[ua][1]
#define lsb son[ub][0]
#define rsb son[ub][1]
#define mi (l+r>>1)
#define LL long long
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
const int mod=201314;
int n,q,rt[maxn],tr[maxn<<7],mk[maxn<<7],son[maxn<<7][2],ver[maxn<<7],fir[maxn],nxt[maxn],v[maxn],cnt,fa[maxn];
int dfn[maxn],tim,wson[maxn],siz[maxn],top[maxn],cntnd;
void ade(int u1,int v1){v[cnt]=v1,nxt[cnt]=fir[u1],fir[u1]=cnt++;}
void getsiz(int u)
{
siz[u]=1;
view(u,k)if(v[k]!=fa[u])
{
getsiz(v[k]),siz[u]+=siz[v[k]];
if(siz[v[k]]>siz[wson[u]])wson[u]=v[k];
}
}
void gettop(int u,int anc)
{
top[u]=anc,dfn[u]=++tim;
if(wson[u])gettop(wson[u],anc);
view(u,k)if(v[k]!=fa[u]&&v[k]!=wson[u])gettop(v[k],v[k]);
}
int mo(int x){if(x>=mod)return x-mod;if(x<0)return x+mod;return x;}
int build(int l,int r)
{
int u=++cntnd;
if(l==r){return u;}
ls=build(l,mi),rs=build(mi+1,r);
return u;
}
int add(int u,int l,int r,int x,int y,int vers)
{
int nu=vers==ver[u]?u:++cntnd;
if(x<=l&&r<=y){son[nu][0]=ls,son[nu][1]=rs,ver[nu]=vers,tr[nu]=mo(tr[u]+r-l+1),mk[nu]=mo(mk[u]+1);return nu;}
ver[nu]=vers,tr[nu]=mo(tr[u]+y-x+1),mk[nu]=mk[u];
if(x<=mi)son[nu][0]=add(ls,l,mi,x,min(mi,y),vers);
else son[nu][0]=ls;
if(y>mi)son[nu][1]=add(rs,mi+1,r,max(x,mi+1),y,vers);
else son[nu][1]=rs;
return nu;
}
int ask(int ua,int ub,int l,int r,int x,int y,int ad)
{
if(x<=l&&r<=y){return mo(mo(tr[ua]-tr[ub])+(LL)ad*(LL)(y-x+1)%mod);}
int lans=0,rans=0;
if(x<=mi)lans=ask(lsa,lsb,l,mi,x,min(mi,y),mo(ad+mo(mk[ua]-mk[ub])));
if(y>mi)rans=ask(rsa,rsb,mi+1,r,max(x,mi+1),y,mo(ad+mo(mk[ua]-mk[ub])));
return mo(lans+rans);
}
int main()
{
memset(fir,-1,sizeof(fir));
n=read(),q=read();
rep(i,2,n)fa[i]=read()+1,ade(fa[i],i);
getsiz(1),gettop(1,1);rt[0]=build(1,n);
rep(i,1,n)
{
rt[i]=rt[i-1];int x=i;
while(top[x]!=1){rt[i]=add(rt[i],1,n,dfn[top[x]],dfn[x],i);x=fa[top[x]];}
rt[i]=add(rt[i],1,n,1,dfn[x],i);
}
while(q--)
{
int l=read()+1,r=read()+1,x=read()+1,ans=0;
while(top[x]!=1){ans=mo(ans+ask(rt[r],rt[l-1],1,n,dfn[top[x]],dfn[x],0));x=fa[top[x]];}
ans=mo(ans+ask(rt[r],rt[l-1],1,n,1,dfn[x],0));
write(ans);
}
return 0;
}

并不对劲的bzoj3626:loj2558:p4211:[LNOI2014]LCA的更多相关文章

  1. P4211 [LNOI2014]LCA

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

  2. P4211 [LNOI2014]LCA LCT

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

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

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

  4. 洛谷 P4211 [LNOI2014]LCA (树链剖分+离线)

    题目:https://www.luogu.org/problemnew/solution/P4211 相当难的一道题,其思想难以用言语表达透彻. 对于每个查询,区间[L,R]中的每个点与z的lca肯定 ...

  5. [火星补锅] 非确定性有穷状态决策自动机练习题Vol.3 T3 && luogu P4211 [LNOI2014]LCA 题解

    前言: 这题感觉还是很有意思.离线思路很奇妙.可能和二次离线有那么一点点相似?当然我不会二次离线我就不云了. 解析: 题目十分清真. 求一段连续区间内的所有点和某个给出的点的Lca的深度和. 首先可以 ...

  6. Luogu P4211 [LNOI2014]LCA

    我去这道题的Luogu评级是假的吧,这都算黑题. 我们首先考虑把操作离线不强制在线的题目离线一下一般都要方便些 考虑差分,我们用\(f(x)\)表示\([1,x]\)之间的点与\(z\)的答案,那么显 ...

  7. 洛谷$P4211\ [LNOI2014]\ LCA$ 树链剖分+线段树

    正解:树剖+线段树 解题报告: 传送门$QwQ$ 看到$dep[lca]$啥的就想到之前托腮腮$CSP$模拟$D1T3$的那个套路,,, 然后试下这个想法,于是$dep[lca(x,y)]=\sum_ ...

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

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

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

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

随机推荐

  1. 理工个人积分赛最后一场(FZU)G - 五子棋,坑爹的大水题~~

    Problem 1490 五子棋 Time Limit: 1000 mSec Memory Limit : 32768 KB  Problem Description 五子棋是起源于中国古代的传统黑白 ...

  2. SpringBoot自定义Filter

    SpringBoot自定义Filter SpringBoot自动添加了OrderedCharacterEncodingFilter和HiddenHttpMethodFilter,当然我们可以自定 义F ...

  3. Pollard rho模板

    #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #in ...

  4. msp430项目编程21

    msp430中项目---直流电机控制系统 1.定时器工作原理 2.电路原理说明 3.代码(显示部分) 4.代码(功能实现) 5.项目总结 msp430项目编程 msp430入门学习

  5. python学习之-- RabbitMQ 消息队列

    记录:异步网络框架:twisted学习参考:www.cnblogs.com/alex3714/articles/5248247.html RabbitMQ 模块 <消息队列> 先说明:py ...

  6. 从零开始写STL—set/map

    这一部分只要把搜索树中暴露的接口封装一下,做一些改动. set源码剖析 template<typename T> class set { public: typedef T key_typ ...

  7. topcoder 649 DIV2

    8 A:模拟 9:B:终于看懂题目... 题意:最多分解K次 每分钟一个数可以分解成两个数 或者-1: 关键字:DP,记忆花搜索. DP[I][J]=min(dp[i][j],1+max(dp[ii] ...

  8. ORA-01034: ORACLE not available 出错

    调用db.rlogon("sm/sm")出现以下错误 ORA-01034: ORACLE not availableORA-27101: shared memory realm d ...

  9. Java二维码的解码和编码

    原文:http://www.open-open.com/code/view/1430906793866 import java.io.File; import java.util.Hashtable; ...

  10. Dialog集合

    点击查看原文 demo下载地址http://download.csdn.net/detail/metis100/8498401 安卓开发一年.開始想整理些资料成库,以备日后高速开发. 第一天,整理了经 ...