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. C语言二维数组作业

    一.PTA实验作业 题目1:7-3 出生年 1. 本题PTA提交列表 2. 设计思路 1.声明一个函数different()用来计算一个年份的不同数字个数 2.定义y(y是来计算符合要求的年份的量), ...

  2. 201421123042 《Java程序设计》第3周学习总结

    #Week03-面向对象入门 1. 本周学习总结 1.1写出你认为本周学习中比较重要的知识点关键词,如类.对象.封装等 本周学习关键词:类,对象,封装,关键词:final,this,statis. 1 ...

  3. mysql命令行大全

      1.连接Mysql 格式: mysql -h主机地址 -u用户名 -p用户密码1.连接到本机上的MYSQL.首先打开DOS窗口,然后进入目录mysql\bin,再键入命令mysql -u root ...

  4. css中的em 简单教程 -- 转

    先附上原作的地址: https://www.w3cplus.com/css/px-to-em 习惯性的复制一遍~~~~ -------------------------------我是分界线---- ...

  5. 移动端300ms与点透总结

    300ms,主要发生在mobile 为啥会出现300ms延迟现象 浏览器想知道用户是否dobule tap(双击缩放) 下列情况不会出现300ms延迟 桌面浏览器 meta的viewport设置了us ...

  6. istio入门(00)istio的学习资源

    官网:https://istio.io/ 理论知识: http://www.uml.org.cn/wfw/201710131.asp 环境搭建: http://dockone.io/article/2 ...

  7. SpringCloud的服务注册中心(三) - 进一步了解 Eureka

    一.服务治理参与者 服务注册中心: eureka-server 服务提供者:HELLO-SERVICE 服务消费者 :HELLO-CONSUMER 很多时候,客户端既是服务提供者又是服务消费者,-&g ...

  8. GIT入门笔记(1)- Git的基本概念

    一.概念和定义 1.git是什么 许多人习惯用复制整个项目目录的方式来保存不同的项目版本,或许还会改名加上备份时间以示区别.这么做唯一的好处就是简单.不过坏处也不少:有时候会混淆所在的工作目录,一旦弄 ...

  9. apigw鉴权分析(1-4)新浪微博开放平台 - 鉴权分析

    一.访问入口 http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E 微博开放接口的调用,如 ...

  10. GridControl的常用操作

    1.GridView的回车跳转单元格和换行 private void gridView1_KeyPress(object sender, KeyPressEventArgs e)        {   ...