【洛谷5439】【XR-2】永恒(树链剖分,线段树)

题面

洛谷

题解

首先两个点的\(LCP\)就是\(Trie\)树上的\(LCA\)的深度。

考虑一对点的贡献,如果这两个点不具有祖先关系,那么这对点被计算的次数是\(size[u]*size[v]\)次。否则具有祖先关系,假设\(u\)是\(v\)祖先,则是\(size[v]*(n-size[u]+1)\)次。

于是先考虑所有点不具有祖先关系,再减去有祖先关系的情况就好了。

然后现在知道了统计的次数,还需要知道统计的值,显然这个\(len\)可以从\(LCA\)到根节点在每个点都统计一次,那么就是每次链加链求和就行了。

怎么算就看代码吧。。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 300300
#define MOD 998244353
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,m,rt,ans,a[MAX];
vector<int> E[MAX],TE[MAX];
int dep[MAX],fa[MAX],sz[MAX],hson[MAX],top[MAX],dfn[MAX],tim;
void dfs1(int u,int ff)
{
fa[u]=ff;dep[u]=dep[ff]+1;sz[u]=1;
for(int v:TE[u])
{
dfs1(v,u),sz[u]+=sz[v];
if(sz[v]>sz[hson[u]])hson[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp;dfn[u]=++tim;
if(hson[u])dfs2(hson[u],tp);
for(int v:TE[u])if(v!=hson[u])dfs2(v,v);
}
#define lson (now<<1)
#define rson (now<<1|1)
int sum[MAX<<2],tag[MAX<<2];
void Modify(int now,int l,int r,int L,int R,int w)
{
if(L<=l&&r<=R)
{
sum[now]=(sum[now]+1ll*(r-l+1)*w)%MOD;
tag[now]=(tag[now]+w)%MOD;
return;
}
int mid=(l+r)>>1;
if(L<=mid)Modify(lson,l,mid,L,R,w);
if(R>mid)Modify(rson,mid+1,r,L,R,w);
sum[now]=(sum[lson]+sum[rson]+1ll*tag[now]*(r-l+1))%MOD;
}
int Query(int now,int l,int r,int L,int R)
{
if(L==l&&r==R)return sum[now];
int mid=(l+r)>>1,ret=1ll*tag[now]*(R-L+1)%MOD;
if(R<=mid)return (ret+Query(lson,l,mid,L,R))%MOD;
if(L>mid)return (ret+Query(rson,mid+1,r,L,R))%MOD;
return (0ll+ret+Query(lson,l,mid,L,mid)+Query(rson,mid+1,r,mid+1,R))%MOD;
}
void Modify(int u,int w){while(u)Modify(1,1,m,dfn[top[u]],dfn[u],w),u=fa[top[u]];}
int Query(int u){int s=0;while(u)s=(s+Query(1,1,m,dfn[top[u]],dfn[u]))%MOD,u=fa[top[u]];return s;}
void dfs(int u){sz[u]=1;for(int v:E[u])dfs(v),sz[u]+=sz[v];}
void DFS(int u)
{
ans=(ans+1ll*sz[u]*Query(a[u])%MOD)%MOD;
Modify(a[u],MOD-sz[u]);
for(int v:E[u])
{
Modify(a[u],n-sz[v]);
DFS(v);
Modify(a[u],MOD-(n-sz[v]));
}
Modify(a[u],sz[u]);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)E[read()].push_back(i);
for(int i=1;i<=m;++i)TE[read()].push_back(i);
scanf("%*s");
for(int i=1;i<=n;++i)a[i]=read();
for(int v:TE[1])dfs1(v,0),dfs2(v,v);
dfs(E[0][0]);
for(int i=1;i<=n;++i)ans=(ans+1ll*sz[i]*Query(a[i]))%MOD,Modify(a[i],sz[i]);
for(int i=1;i<=n;++i)Modify(a[i],MOD-sz[i]);
DFS(E[0][0]);
printf("%d\n",ans);
return 0;
}

最新文章

  1. Redis到底该如何利用(三)?
  2. 在cxf中使用配置避免增加字段导致客户端必须更新、同步实体属性的问题
  3. maven运行javaWeb项目
  4. 重学STM32----(二)
  5. .NET设计模式(6):原型模式(Prototype Pattern)(转)
  6. ubuntu mint 开机启动项管理
  7. 修改MYSQL最大连接数的2种方法
  8. SQL Server dbcc checkdb 修复
  9. tcp粘包和拆包的处理方案
  10. .NET 开源项目 Anet 介绍
  11. 保存配置,获取配置,XML
  12. Python开发【第十一篇】:MySQL
  13. Android AIDL 实例
  14. Redirection
  15. Vue系列之 =&gt; 组件中的data和methods
  16. Servlet简介及其生命周期详解
  17. 安装hyperledger fabric V1.0.0-beta
  18. 重启虚拟目录或站点,不重启iis
  19. hdu3038 How many answers are wrong【并查集】
  20. os.stat(filename).st_size 文件信息

热门文章

  1. 记一次hosts配置内容过多引起的故障
  2. Spring Boot配置过滤器的两种方式
  3. .NET MVC5简介(五)管道处理模型IHttpModule
  4. ASP.NET Core框架深度学习(四)宿主对象
  5. 转:用 Python 一键分析你的上网行为, 看是在认真工作还是摸鱼
  6. 利用Python突破验证码限制
  7. Xamarin学习(一)---- 环境准备
  8. 算法基础:BFS和DFS的直观解释
  9. 【LeetCode】437. 路径总和 III
  10. CPU 架构SMP/NUMA,调优