1681 公共祖先

基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
 

有一个庞大的家族,共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
/*
51 nod 1681 公共祖先 (主席树+dfs序) problem:
给你两棵树, 两个节点之间的值定义为在两个棵树中有多少一直是它们的公共祖先
求任意两个点的亲密度的总和 solve:
问题可以转换成每个点能够成为多少次公共祖先. 如果lca一直是a,b的公共祖先, 那么
a,b一定在lca的子树中. 所以找出两棵树中lca点的子树中的相同点的个数,就能计算出多少对点
在两棵树中都有lca这个公共祖先. 先处理出a树的dfs序,然后用其作为b树中dfs序的值. 在a树中,如果u在lca的子树中,那么它的序号
大于dfa[lca]小于等于eda[lca],即进出值. 所以在b树的lca的子树中找出序号在[dfa[lca],eda[lca]]
之间的个数(可以主席树维护), 就是lca子树所含相同点的个数. hhh-2016/09/16-11:36:14
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <math.h>
#include <queue>
#include <set>
#include <map>
//#define lson i<<1
//#define rson i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define scanfi(a) scanf("%d",&a)
#define scanfs(a) scanf("%s",a)
#define scanfl(a) scanf("%I64d",&a)
#define scanfd(a) scanf("%lf",&a)
#define key_val ch[ch[root][1]][0]
#define eps 1e-7
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const ll mod = 1e9+7;
const int maxn = 100010;
const double PI = acos(-1.0); template<class T> void read(T&num)
{
char CH;
bool F=false;
for(CH=getchar(); CH<'0'||CH>'9'; F= CH=='-',CH=getchar());
for(num=0; CH>='0'&&CH<='9'; num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p)
{
if(!p)
{
puts("0");
return;
}
while(p) stk[++ tp] = p%10, p/=10;
while(tp) putchar(stk[tp--] + '0');
putchar('\n');
} struct Edge
{
int to,next;
};
Edge edge[maxn*2];
int tot,head[maxn];
int in[maxn];
int cnt;
void ini()
{
tot = 0;
cnt = 0;
memset(in,0,sizeof(in));
memset(head,-1,sizeof(head));
}
void add_edge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
int dfa[maxn],dfb[maxn],ta[maxn],tb[maxn];
int eda[maxn],edb[maxn];
void dfs(int u,int pre,int flag)
{
if(!flag) dfa[u] = ++ cnt, ta[u] = cnt;
else dfb[u] = ++ cnt, tb[cnt] = ta[u];
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v == pre)continue;
dfs(v,u,flag);
}
if(!flag) eda[u] = cnt;
else edb[u] = cnt;
} int toa;
int lson[maxn * 30],rson[maxn * 30] ;
ll c[maxn * 30]; int build(int l,int r)
{
int root = toa ++ ;
c[root] = 0;
if(l != r)
{
int mid = (l+r) >> 1;
build(l,mid);
build(mid+ 1,r);
}
return root ;
}
int n;
int update(int root,int pos,ll val)
{
int newroot = toa ++ ,tmp = newroot;
c[newroot ] = c[root] + val;
int l = 1,r = n; while(l < r)
{
int mid = (l+r) >> 1;
if(pos <= mid)
{
lson[newroot] = toa ++ ,rson[newroot] = rson[root];
newroot = lson[newroot],root = lson[root];
r = mid;
}
else
{
rson[newroot] = toa ++ ,lson[newroot] = lson[root];
newroot = rson[newroot] ,root = rson[root];
l = mid + 1;
}
c[newroot] = c[root] + val;
}
return tmp;
} ll query(int root1,int root2,int la,int ra,int l,int r)
{
if(l >= la && r <= ra)
{
return c[root2] - c[root1];
}
int mid = (l + r) >> 1;
ll ans = 0;
if(la <= mid)
{
ans += query(lson[root1],lson[root2],la,ra,l,mid);
}
if(ra > mid)
{
ans += query(rson[root1],rson[root2],la,ra,mid+1,r);
}
return ans;
} void cal(int flag)
{
int u,v;
ini();
for(int i = 1; i < n; i++)
{
read(u),read(v);
add_edge(u,v);
add_edge(v,u);
in[v] ++ ;
}
for(int i = 1; i <= n;i++)
{
if(!in[i])
{
dfs(i,-1,flag);
break;
}
}
}
int T[maxn];
int main()
{
// freopen("in.txt","r",stdin);
read(n);
toa = 0;
cal(0);
cal(1);
T[0] = build(1,n);
for(int i = 1;i <= n;i++)
{
T[i] = update(T[i-1],tb[i],1);
}
ll ans = 0;
for(int i = 1;i <= n;i++)
{
int l = dfb[i],r = edb[i];
ll t = query(T[l],T[r],dfa[i],eda[i],1,n);
ans += 1LL*t*(t-1)/2;
}
printf("%I64d\n",ans);
return 0;
}

  

51 nod 1681 公共祖先 (主席树+dfs序)的更多相关文章

  1. 「10.19」最长不下降子序列(DP)·完全背包问题(spfa优化DP)·最近公共祖先(线段树+DFS序)

    我又被虐了... A. 最长不下降子序列 考场打的错解,成功调了两个半小时还是没A, 事实上和正解的思路很近了,只是没有想到直接将前$D$个及后$D$个直接提出来 确实当时思路有些紊乱,打的时候只是将 ...

  2. 【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序

    [BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n n ...

  3. BZOJ3772 精神污染 【主席树 + dfs序】

    题目 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户,海 ...

  4. 刷题总结——谈笑风生(主席树+dfs序的应用)

    题目: Description 设T 为一棵有根树,我们做如下的定义:• 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称“a比b不知道高明到哪里去了”.• 设a 和 b 为 T 中的两个不同 ...

  5. bzoj 3772 精神污染 主席树+dfs序

    精神污染 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 637  Solved: 177[Submit][Status][Discuss] Descri ...

  6. 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 321[Submit][Sta ...

  7. 【SPOJ】10628. Count on a tree(lca+主席树+dfs序)

    http://www.spoj.com/problems/COT/ (速度很快,排到了rank6) 这题让我明白了人生T_T 我知道我为什么那么sb了. 调试一早上都在想人生. 唉. 太弱. 太弱. ...

  8. BZOJ 2809: [Apio2012]dispatching [主席树 DFS序]

    传送门 题意:查询树上根节点值*子树中权值和$\le m$的最大数量 最大值是多少 求$DFS$序,然后变成区间中和$\le m$最多有几个元素,建主席树,然后权值线段树上二分就行了 $WA$:又把边 ...

  9. BZOJ_1803_Spoj1487 Query on a tree III_主席树+dfs序

    BZOJ_1803_Spoj1487 Query on a tree III_主席树 Description You are given a node-labeled rooted tree with ...

随机推荐

  1. MySQL 操作详解

    MySQL 操作详解 一.实验简介 本节实验中学习并实践 MySQL 上创建数据库.创建表.查找信息等详细的语法及参数使用方法. 二.创建并使用数据库 1. 创建并选择数据库 使用SHOW语句找出服务 ...

  2. 利用Python爬取新浪微博营销案例库并下载到本地

    from bs4 import BeautifulSoup import requests,urllib.request,urllib.parse import json import time im ...

  3. python day1 基本语法作业

    一.过7 start =1 while start<=10: if start !=7: print(start) start +=1 二.100以内的和 sum = 0 start = 1 w ...

  4. 使用SecureCRTP 连接生产环境的web服务器和数据库服务器

    一.使用SecureCRTP 连接生产环境的web服务器 首先,需要知道以下参数信息: 1.web服务器的ip地址     2.服务器的端口号    3.会话连接的用户名和密码   4.服务器的用户名 ...

  5. bzoj千题计划271:bzoj4869: [六省联考2017]相逢是问候

    http://www.lydsy.com/JudgeOnline/problem.php?id=4869 欧拉降幂+线段树,每个数最多降log次,模数就会降为1 #include<cmath&g ...

  6. BAT齐聚阿里安全-ASRC生态大会:呼吁联合共建网络安全白色产业链

    图说:近日,阿里安全-ASRC生态大会在杭州举行,包括BAT在内的20余家国内知名互联网企业代表,回顾过去一年网络安全面临的问题与挑战,共谋生态安全治理思路. "123456.111111. ...

  7. selenium在页面中多个fream的定位

    在做页面元素定位的时候,遇到多fream的页面定位比较困难,需要先去切换到元素所在的fream才能成功定位. 1,切换到目标fream: driver.switch_to.frame('freamID ...

  8. 原生Ajax用法——一个简单的实例

    Ajax全名(Asynchronous(异步) JavaScript and XML )是可以实现局部刷新的 在讲AJax之前我们先用简单的实例说一下同步和异步这个概念 /*异步的概念(就是当领导有一 ...

  9. linux下的Shell编程(4)特殊的变量和占位符

    $#表示包括$0在内的命令行参数的个数.在Shell中,脚本名称本身是$0,剩下的依次是$0.$1.$2-.${9},等等. $*表示整个参数列表,不包括$0,也就是说不包括文件名的参数列表. $?表 ...

  10. React中路由传参及接收参数的方式

    注意:  路由表改变后要重启服务      方式 一:          通过params         1.路由表中                     <Route path=' /s ...