专栏文章

题解:P11624 [迷宫寻路 Round 3] 挂掉的模板

P11624题解参与者 2已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@miqduegl
此快照首次捕获于
2025/12/04 03:11
3 个月前
此快照最后确认于
2025/12/04 03:11
3 个月前
查看原文
考虑几种对答案有贡献的点对 (u,v)(u,v)
d(u)\operatorname{d}(u) 表示 uu 的深度,ss 表示根节点。
  1. d(u)=d(v)\operatorname{d}(u) = \operatorname{d}(v)
  2. u=vu = v
  3. (u=s)(v=s)(u = s) \vee (v = s)
  4. LCA(u,v)=sLCA(u,v) = s
c(x)\operatorname{c}(x) 表示深度为 xx 的节点个数,s(u)\operatorname{s}(u) 表示 uu 为根节点的子树有多少节点(含根节点),soni(1itot)son_i(1 \le i \le tot) 表示根节点的第 ii 个儿子。
分别计算贡献,情况 2,3 显然不再赘述。
对于情况 1,有 2×i=1nj=1c(i)1j2 \times {\sum_{i=1}^{n}\sum_{j=1}^{\operatorname{c}(i)-1}j} 对于情况 4,有 i=1tots(soni)(nsoni1)\sum_{i=1}^{tot}\operatorname{s}(son_i)*(n-son_i-1)
对于点对 (u,v)(u,v),若 d(u)=d(v)\operatorname{d}(u) = \operatorname{d}(v)u,vu,v 都在根节点的两个不同子树中,它会被重复计算。
解决方法:情况 1,统计每个 sonison_i 的答案累加即可,这样操作后情况 1 中的点对都属于同一个子树,情况 4 中的点对都不属于同一个子树。
CODE
CPP
#define MAXN 1000005
int n;
int s;
struct Edge{
    int u,v,nxt;
}e[MAXN];
int head[MAXN],cnt;
inline void addedge(int u,int v){
    ++cnt;
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].nxt=head[u];
    head[u]=cnt;
}
long long ans=0;
int dep[MAXN],num[MAXN];//深度,某一深度上的节点数
long long sz[MAXN];//子树大小
int dfs(int u,int fa){
    dep[u]=dep[fa]+1;++num[dep[u]];
    sz[u]++;
    for (int i = head[u];i;i = e[i].nxt){
        int v=e[i].v;
        sz[u]+=dfs(v,u);
    }
    return sz[u];
}
long long sum[MAXN];
int main(){
    n=read();int fa;
    if (n==1){
        puts("1");
        return 0;
    }
    for (int i = 1;i <= n;i ++){
        fa=read();
        if (fa==i){s=i;continue;}
        addedge(fa,i);
    }
    for (int i = 1;i <= n;i ++) sum[i]=sum[i-1]+i;
    for (int i = head[s]; i ;i = e[i].nxt){//分子树讨论
        int v=e[i].v;
        fill(num+1,num+n+1,0);
        dfs(v,s);
        for (int j = 1;j <= n;j ++) ans+=sum[num[j]-1]*2;//情况1
        ans+=sz[v]*(n-sz[v]-1);情况4
    }
    cout <<ans+n+(n-1)*2;//情况2,3
    return 0;
}
tips:数组也要开 ll,或计算时强制转换。

评论

2 条评论,欢迎与作者交流。

正在加载评论...