题目大意

有一棵有\(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. hexo干货系列:(总纲)搭建独立博客初衷

    前言 我是一名程序员,以前知识整理都是整理在为知笔记上,博客用的比较少,更别说是使用独立博客,因为不会... 2016年过年在家期间偶然的机会萌发了自己要搭建一个属于自己的独立博客的想法,于是就有了下 ...

  2. POJ-1067取石子游戏,威佐夫博弈范例题/NYOJ-161,主要在于这个黄金公式~~

    取石子游戏 Time Limit: 1000MS   Memory Limit: 10000K              Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取 ...

  3. PTA 03-树3 Tree Traversals Again (25分)

    题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/667 5-5 Tree Traversals Again   (25分) An inor ...

  4. Linux下建立虚拟内存

    查看目前虚拟内存状况 free -m -m表示以MB的单位显示 建立虚拟内存文件 先用df -h确认要放虚拟内存文件的位置,假设为 /data/swap/swap1 创建2G的虚拟内存并启用: dd ...

  5. python学习之-- mysql模块和sqlalchemy模块

    简单介绍python下操作mysql数据库模块有2个:pyhton-mysqldb  和 pymysql 说明:在python3中支持mysql 的模块已经使用pymysql替代了MysqlDB(这个 ...

  6. Milking Time---poj3616

    Description Bessie is such a hard-working cow. In fact, she is so focused on maximizing her producti ...

  7. zookeeper原理浅析(二)

    参考:https://www.cnblogs.com/leocook/p/zk_1.html 代码:https://github.com/littlecarzz/zookeeper 1. 数据模型 1 ...

  8. java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet

    新建Maven 项目的时候报错: java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet ...

  9. iOS macOS的后渗透利用工具:EggShell

    EggShell是一款基于Python编写的iOS和macOS的后渗透利用工具.它有点类似于metasploit,我们可以用它来创建payload建立侦听.此外,在反弹回的session会话也为我们提 ...

  10. linux设备驱动归纳总结

    前言: (总结已经基本写完,这段时间我会从新排版和修正.错误总会有的,望能指正!) 前段时间学习了嵌入式驱动,趁着没开始找工作,这段时间我会每天抽出时间来复习. 我的总结是根据学习时的笔记(李杨老师授 ...