【CF860E】Arkady and a Nobody-men

题意:给你一棵n个点的有根树。如果b是a的祖先,定义$r(a,b)$为b的子树中深度小于等于a的深度的点的个数(包括a)。定义$z(a)=\sum\limits r(a,b)$(b是a的祖先)。要你求出每个点的z值。

$n\le 5\times 10^5$

题解:一开始naive的思路:将所有点按深度排序,将深度相同的点统一处理,统计答案时相当于链加,链求和,用树剖+树状数组搞一搞,时间复杂度$O(n\log^2n)$。

后来看题解发现我这个想法简直菜爆了。我们先从树形DP的角度去想,先给出转移方程:

$ans(x)=ans(fa(x))+dep(x)+ans'(x)$,ans'(x)表示与a深度相同的点 对a的贡献。

现在问题变成了求ans',我们考虑在每个点对的lca处统计贡献。具体地,我们对于每个点x,维护若干个三元组(d,a,cnt)表示x的子树中有cnt个d级子孙,其中一个子孙为a。DP的过程就相当于在父亲节点处将所有儿子节点的三元组合并,在合并时顺便统计贡献。

具体地,合并方式如下:假如x有两个儿子,它们有三元组$(d,a,cnt_a)$和$(d,b,cnt_b)$,则:

1.$ans'(a)+=dep(x)\times cnt_b$
2.$ans'(b)+=dep(x)\times cnt_a$
3.得到新三元组$(d,a,cnt_a+cnt_b)$

但是后面的点 对b的贡献呢?我们发现后面的点 对a和b的贡献就是相同的了,所以我们建一个新图,在新图中从a到b连一条长度为$ans'(b)-ans'(a)$的边,最后在新图上DFS一下,最最后统计一下ans数组即可。

以上过程采用长链剖分优化,由于一开始的三元组个数为n,则每次合并都会减少一个三元组,所以时间复杂度O(n)。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int maxn=500010;
typedef long long ll;
ll ans[maxn];
struct node
{
int v,x;
node() {}
node(int a,int b) {v=a,x=b;}
}mem[maxn<<1],*f[maxn],*now=mem;
int n,cnt,Cnt,rt;
int to[maxn],nxt[maxn],head[maxn],dep[maxn],md[maxn],son[maxn],fa[maxn];
bool vis[maxn];
int To[maxn],Nxt[maxn],Head[maxn];
ll Val[maxn];
inline void add(int a,int b)
{
to[cnt]=b,nxt[cnt]=head[a],head[a]=cnt++;
}
inline void Add(int a,int b,ll c)
{
To[Cnt]=b,Val[Cnt]=c,Nxt[Cnt]=Head[a],Head[a]=Cnt++;
}
void dfs1(int x)
{
md[x]=0;
for(int i=head[x];i!=-1;i=nxt[i])
{
dep[to[i]]=dep[x]+1,dfs1(to[i]);
if(md[to[i]]+1>md[x]) md[x]=md[to[i]]+1,son[x]=to[i];
}
}
void dfs2(int x)
{
if(f[x]==NULL) f[x]=now,now+=md[x]+2;
if(son[x]) f[son[x]]=f[x]+1,dfs2(son[x]);
f[x][0]=node(1,x);
for(int i=head[x];i!=-1;i=nxt[i]) if(to[i]!=son[x])
{
dfs2(to[i]);
for(int j=0;j<=md[to[i]];j++)
{
node a=f[x][j+1],b=f[to[i]][j];
ans[b.x]+=1ll*dep[x]*a.v;
ans[a.x]+=1ll*dep[x]*b.v;
Add(a.x,b.x,ans[b.x]-ans[a.x]);
f[x][j+1]=node(a.v+b.v,a.x);
}
}
}
void dfs3(int x)
{
for(int i=Head[x];i!=-1;i=Nxt[i]) ans[To[i]]=ans[x]+Val[i],dfs3(To[i]);
}
void dfs4(int x)
{
for(int i=head[x];i!=-1;i=nxt[i]) ans[to[i]]+=ans[x]+dep[x],dfs4(to[i]);
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
int main()
{
n=rd();
int i;
memset(head,-1,sizeof(head)),memset(Head,-1,sizeof(Head));
for(i=1;i<=n;i++)
{
fa[i]=rd();
if(!fa[i]) rt=i;
else add(fa[i],i);
}
dep[rt]=1,dfs1(rt);
dfs2(rt);
for(i=0;i<=md[rt];i++) dfs3(f[rt][i].x);
dfs4(rt);
for(i=1;i<=n;i++) printf("%lld ",ans[i]);
return 0;
}

【CF860E】Arkady and a Nobody-men 长链剖分的更多相关文章

  1. [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分

    题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...

  2. LOJ3053 十二省联考2019 希望 容斥、树形DP、长链剖分

    传送门 官方题解其实讲的挺清楚了,就是锅有点多-- 一些有启发性的部分分 L=N 一个经典(反正我是不会)的容斥:最后的答案=对于每个点能够以它作为集合点的方案数-对于每条边能够以其两个端点作为集合点 ...

  3. BZOJ 3653: 谈笑风生(离线, 长链剖分, 后缀和)

    题意 给你一颗有 \(n\) 个点并且以 \(1\) 为根的树.共有 \(q\) 次询问,每次询问两个参数 \(p, k\) .询问有多少对点 \((p, a, b)\) 满足 \(p,a,b\) 为 ...

  4. 2019.03.11 COGS2652 秘术(天文密葬法)(分数规划+长链剖分)

    传送门 题意:nnn个点的树,每个点两个值a,ba,ba,b,问长度为mmm的路径∑ai∑bi\frac{\sum a_i}{\sum b_i}∑bi​∑ai​​的最大值. 思路:一眼要01分数规划, ...

  5. 【BZOJ3522】【BZOJ4543】【POI2014】Hotel 树形DP 长链剖分 启发式合并

    题目大意 ​ 给你一棵树,求有多少个组点满足\(x\neq y,x\neq z,y\neq z,dist_{x,y}=dist_{x,z}=dist_{y,z}\) ​ \(1\leq n\leq 1 ...

  6. 【Vijos】lxhgww的奇思妙想(长链剖分)

    题面 给定一棵树,每次询问一个点的\(k\)次祖先,强制在线. Vijos 题解 长链剖分. 链接暂时咕咕咕了. 现在可以戳链接看题解了 #include<iostream> #inclu ...

  7. 【BZOJ4543】Hotel加强版(长链剖分)

    [BZOJ4543]Hotel加强版(长链剖分) 题面 BZOJ,没有题面 洛谷,只是普通版本 题解 原来我们的\(O(n^2)\)做法是设\(f[i][j]\)表示以\(i\)为根的子树中,距离\( ...

  8. 【BZOJ3653】谈笑风生(长链剖分)

    [BZOJ3653]谈笑风生(长链剖分) 题面 BZOJ 洛谷 权限题啊.... 题解 首先根据题目给的条件,发现\(a,b\)都要是\(c\)的父亲. 所以这三个点是树上的一条深度单增的链. 因为\ ...

  9. 【CF1009F】Dominant Indices(长链剖分)

    [CF1009F]Dominant Indices(长链剖分) 题面 洛谷 CF 翻译: 给定一棵\(n\)个点,以\(1\)号点为根的有根树. 对于每个点,回答在它子树中, 假设距离它为\(d\)的 ...

随机推荐

  1. web_submit_data详解

    定义:处理无状态或者上下文无关的表单提交.它用来生成表单的GET或POST请求,这些请求与Form自动生成的请求是一样的,发送这些请求时不需要表单上下文. 函数形式:web_submit_data( ...

  2. Android Material Design控件学习(三)——使用TextInputLayout实现酷市场登录效果

    前言 前两次,我们学习了 Android Material Design控件学习(一)--TabLayout的用法 Android Material Design控件学习(二)--Navigation ...

  3. Ajax请求全局配置

    摘要: jQuery已经成为项目中最常见的js库,也是前端开发最喜欢使用的库.下面是在项目中封装了jQuery的Ajax,分享给大家. 代码: // ajax 请求参数 var ajaxSetting ...

  4. 时间戳Id

    ID:格式据1970.1.1毫秒数 1535091029740  13位 问题:高并发,分布式明显会有问题,网上有雪花算法,但是位数跟我需要的不一样,暂时不考虑,以后研究再用. 参考: https:/ ...

  5. Eclipse------启动Server时出现弹窗Server at localhost was unable to start within 45 seconds.

    弹窗详细信息: Server Tomcat v8. Server at localhost was unable to start within seconds. If the server requ ...

  6. 5 -- Hibernate的基本用法 --1 3 流行的ORM框架简介

    ⊙ JPA : JPA本身只是一种ORM规范,并不是ORM产品.它是Java EE规范制定者向开源世界学习的结果.JPA实体与Hibernate PO十分相似,甚至JPA实体完全可作为Hibernat ...

  7. GoF--适配器设计模式

    1.概念:  适配器模式(Adapter Pattern)把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. 2.形式  a.类的适配器模式  ...

  8. CSS属性中display="none“与visibility="hidden"的不同

    display="none",元素会从页面移除,不在页面占用位置,当某个元素设置为display="none"时,这个元素后面的元素会移动上来 visibili ...

  9. zabbix中Templates的jmx相关key调试方法

    1.下载 cmdline jmxclient 如果你有一个完美的模版,你可能可以忽略此步.但是大多数情况下你没有.况且 zabbix 默认的 tomcat 模版也不能很好的工作.这时候有一个工具来调试 ...

  10. JavaWeb学习总结(十五)Jsp中提交的表单的get和post的两种方式

    两者的比较: Get方式: 将请求的参数名和值转换成字符串,并附加在原来的URL之后,不安全 传输的数据量较小,一般不能大于2KB: post方式: 数量较大: 请求的参数和值放在HTML的请求头中, ...