JZOJ.5326【NOIP2017模拟8.21】LCA 的统计

Description

 

Input

Output

 

Sample Input

2 2
1 1

Sample Output

17
 

Data Constraint

 

Hint

朴素的O(n2logn)显然会爆,我们需要优化。

这种有公式的题目,我们可以从公式入手,化简公式,简化运算。

其中最常见的就是提取公因式。

这个公式有三个因子,显然lca对于我们来说方便处理些。

我们假设一个点i为某两点的lca,考察它对答案的贡献。

第一种情况就是两点分别在i的不同子树内,设以该点为根的子树的总权值和为sum[i],则对答案的贡献为isum(i)(sum(i)sum(i))  (i'i的儿子)

第二种情况就是有个点在lca上,则对答案的贡献为V(i)sum(i)(其中算了一次两个点在lca上)

累加起来就可以了。

复制代码
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define N 1005005
 5 #define mo 1000000007
 6 using namespace std;
 7 int head[N],next[N],to[N],num,size[N],n,m;
 8 long long ans,sum[N],va[N];
 9 void add(int u,int v){
10     num++;
11     next[num]=head[u];
12     to[num]=v;
13     head[u]=num;
14 }
15 void DFS(int x){
16     size[x]=1;
17     sum[x]=va[x];
18     for (int v,i=head[x];i;i=next[i]){
19         v=to[i];
20         DFS(v);
21         size[x]+=size[v];
22         sum[x]=(sum[v]+sum[x])%mo;
23     }
24 }
25 void QAQ(int x){
26     if (size[x]==1) {ans=(va[x]*va[x]%mo*va[x]%mo+ans)%mo; return;}
27     for (int v,i=head[x];i;i=next[i]){
28         v=to[i];
29         QAQ(v);
30         ans=((sum[v])*(sum[x]-sum[v])%mo*va[x]%mo+ans)%mo;
31     }
32     ans=((sum[x]*va[x])%mo*(va[x])%mo+ans)%mo;
33 }
34 int main(){
35     num=0;
36     scanf("%d%lld",&n,&va[1]);
37     for (int u,i=2;i<=n;++i){
38         scanf("%d%lld",&u,&va[i]);
39         add(u,i);
40     }
41     ans=0;
42     DFS(1);
43     QAQ(1);
44     printf("%lld\n",ans%mo);
45     return 0;
46 }
神奇的代码
复制代码

 

本文作者:~Lanly~

本文链接:https://www.cnblogs.com/Lanly/p/7404911.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   ~Lanly~  阅读(192)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.