P4211 [LNOI2014]LCA
解题方法
可以发现一个结论:两个点到根节点的重合路径的长度即为他们
但是
把问题排序,然后离线做就好了。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10;
int read(){
int x=0,f=1;char c=getchar();
while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
int n,m;
struct Seg{
int lzy[N<<2],val[N<<2],len[N<<2];
void build(int u,int l,int r){
len[u]=r-l+1;
if(l==r)return;int mid=(l+r)>>1;
build(u<<1,l,mid);build(u<<1|1,mid+1,r);
return;
}
void pushdown(int u){
if(lzy[u]){
val[u<<1]+=lzy[u]*len[u<<1];
val[u<<1|1]+=lzy[u]*len[u<<1|1];
lzy[u<<1]+=lzy[u];lzy[u<<1|1]+=lzy[u];
lzy[u]=0;
}
return;
}
void pushup(int u){val[u]=val[u<<1]+val[u<<1|1];return;}
void update(int u,int l,int r,int L,int R){
if(L<=l && r<=R){val[u]+=len[u];lzy[u]++;return;}
pushdown(u);int mid=(l+r)>>1;
if(L<=mid)update(u<<1,l,mid,L,R);
if(R>mid)update(u<<1|1,mid+1,r,L,R);
pushup(u);return;
}
int query(int u,int l,int r,int L,int R){
if(L<=l && r<=R)return val[u];
pushdown(u);int mid=(l+r)>>1,res=0;
if(L<=mid)res+=query(u<<1,l,mid,L,R);
if(R>mid)res+=query(u<<1|1,mid+1,r,L,R);
return res;
}
}E;
struct Tree{
int head[N],to[N<<1],last[N<<1],tot;
void add(int u,int v){to[++tot]=v,last[tot]=head[u],head[u]=tot;return;}
int maxson[N],dep[N],top[N],sze[N],cnt,dfn[N],fa[N];
void dfs1(int u,int d){
dep[u]=d;sze[u]=1;
for(int i=head[u];i;i=last[i]){
int v=to[i];dfs1(v,d+1);
sze[u]+=sze[v];
if(sze[v]>sze[maxson[u]])maxson[u]=v;
}
return;
}
void dfs2(int u,int t){
top[u]=t;dfn[u]=++cnt;
if(maxson[u])dfs2(maxson[u],t);
for(int i=head[u];i;i=last[i]){
int v=to[i];if(v!=maxson[u])dfs2(v,v);
}
}
void update(int x){
while(x!=0){E.update(1,1,n,dfn[top[x]],dfn[x]);x=fa[top[x]];}
return;
}
int query(int x){
int res=0;
while(x!=0){res+=E.query(1,1,n,dfn[top[x]],dfn[x]);x=fa[top[x]];}
return res;
}
}T;
struct Q{
int tim,id,z,kd;
bool operator<(const Q A)const{return tim<A.tim;}
}q[N<<1];
int ans[N];
int main(){
n=read(),m=read();E.build(1,1,n);
for(int i=2;i<=n;i++){T.fa[i]=read()+1;T.add(T.fa[i],i);}
T.dfs1(1,1);T.dfs2(1,1);
for(int i=1;i<=m;i++){
int l=read()+1,r=read()+1,z=read()+1;
q[2*i-1].id=q[2*i].id=i;
q[2*i-1].tim=l-1,q[2*i-1].z=z,q[2*i-1].kd=-1;
q[2*i].tim=r,q[2*i].z=z,q[2*i].kd=1;
}
sort(q+1,q+2*m+1);int tim=0;
for(int i=1;i<=2*m;i++){
while(tim<q[i].tim){tim++;T.update(tim);}
ans[q[i].id]+=q[i].kd*T.query(q[i].z);
}
for(int i=1;i<=m;i++)printf("%d\n",ans[i]%201314);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话