51nod1681公共祖先(dfs序+树状数组)

1681 公共祖先

有一个庞大的家族,共n人。已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边)。
在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完全不同了,原来的祖先可能变成了后代,后代变成的同辈……
两个人的亲密度定义为在这两个平行宇宙有多少人一直是他们的公共祖先。
整个家族的亲密度定义为任意两个人亲密度的总和。

Input

第一行一个数n(1<=n<=100000)
接下来n-1行每行两个数x,y表示在第一个平行宇宙x是y的父亲。
接下来n-1行每行两个数x,y表示在第二个平行宇宙x是y的父亲。

Output

一个数,表示整个家族的亲密度。

Input示例

5
1 3
3 5
5 4
4 2
1 2
1 3
3 4
1 5

Output示例

6

solution:

首先想到的是最最暴力的做法,对两棵树的每一个点分别记录它的所有儿子,然后枚举每一对点统计答案。这是O(n³)……然后很容易想到在dfs时记录下上述信息,这样就是O(n²)的。把所有信息记下来显然太暴力了,所以需要一边做一边统计答案。枚举公共祖先,假设有sum个点在两棵树中都是它的后代,那么以这个点为公共祖先的贡献是sum*(sum-1)/2。所以只要快速算出sum就行了。对于第一棵树做dfs,记录下每一个点的入栈时间戳和出栈时间戳,那么两个时间戳中间的点是且都是它的后代。(这一点和树链剖分很像)。然后对第二棵树进行dfs,并根据第一棵树的dfs序维护树状数组。访问到u点时,统计sum1为u的后代的点权和,然后将u点的权+1,访问u的所有儿子,在出栈时记录sum2为此时u的后代的点权和。sum=sum2-sum1。时间复杂度O(n lg n),问题就解决了。

code:

#include<stdio.h>
long long ans;
int de1[100005],num,de2[100005],n,en1,Next1[100005],vet1[100005],head1[100005],en2,Next2[100005],vet2[100005],head2[100005],bit[100005],be[100005],en[100005],root1,root2;
inline void addedge1(int u,int v){de1[v]++;Next1[++en1]=head1[u];vet1[en1]=v;head1[u]=en1;}
inline void addedge2(int u,int v){de2[v]++;Next2[++en2]=head2[u];vet2[en2]=v;head2[u]=en2;}
inline int lowbit(int x){return x&-x;}
inline void add(int x,int y){while(x<=n){bit[x]+=y;x+=lowbit(x);}}
inline int query(int x){int ans=0;while(x){ans+=bit[x];x-=lowbit(x);}return ans;}
void dfs1(int u){
    be[u]=en[u]=++num;
    for(int i=head1[u];i;i=Next1[i])dfs1(vet1[i]);
    en[u]=num;
}
void dfs2(int u){
    long long sum=query(en[u])-query(be[u]-1);
    add(be[u],1);
    for(int i=head2[u];i;i=Next2[i])
        dfs2(vet2[i]);
    sum=query(en[u])-query(be[u]-1)-sum-1;
    ans+=(sum-1ll)*sum>>1;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addedge1(x,y);}
    for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addedge2(x,y);}
    for(int i=1;i<n;i++){if(!de1[i])root1=i;if(!de2[i])root2=i;}
    dfs1(root1);dfs2(root2);
    printf("%lld\n",ans);
    return 0;
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38601996/article/details/78344959
文章标签: dfs 树状数组
个人分类: 树状数组 dfs
上一篇HDU2296(AC自动机+DP)
下一篇一道分治题
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭