1681 公共祖先

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

有一个庞大的家族,共n人。已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边)。

在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完全不同了,原来的祖先可能变成了后代,后代变成的同辈……

两个人的亲密度定义为在这两个平行宇宙有多少人一直是他们的公共祖先。

整个家族的亲密度定义为任意两个人亲密度的总和。

Input
  1. 第一行一个数n(1<=n<=100000)
  2. 接下来n-1行每行两个数x,y表示在第一个平行宇宙xy的父亲。
  3. 接下来n-1行每行两个数x,y表示在第二个平行宇宙xy的父亲。
Output
  1. 一个数,表示整个家族的亲密度。
Input示例
  1. 5
  2. 1 3
  3. 3 5
  4. 5 4
  5. 4 2
  6. 1 2
  7. 1 3
  8. 3 4
  9. 1 5
Output示例
  1. 6
  1. /*
  2. 51 nod 1681 公共祖先 (主席树+dfs序)
  3.  
  4. problem:
  5. 给你两棵树, 两个节点之间的值定义为在两个棵树中有多少一直是它们的公共祖先
  6. 求任意两个点的亲密度的总和
  7.  
  8. solve:
  9. 问题可以转换成每个点能够成为多少次公共祖先. 如果lca一直是a,b的公共祖先, 那么
  10. a,b一定在lca的子树中. 所以找出两棵树中lca点的子树中的相同点的个数,就能计算出多少对点
  11. 在两棵树中都有lca这个公共祖先.
  12.  
  13. 先处理出a树的dfs序,然后用其作为b树中dfs序的值. 在a树中,如果u在lca的子树中,那么它的序号
  14. 大于dfa[lca]小于等于eda[lca],即进出值. 所以在b树的lca的子树中找出序号在[dfa[lca],eda[lca]]
  15. 之间的个数(可以主席树维护), 就是lca子树所含相同点的个数.
  16.  
  17. hhh-2016/09/16-11:36:14
  18. */
  19. #pragma comment(linker,"/STACK:124000000,124000000")
  20. #include <algorithm>
  21. #include <iostream>
  22. #include <cstdlib>
  23. #include <cstdio>
  24. #include <cstring>
  25. #include <vector>
  26. #include <math.h>
  27. #include <queue>
  28. #include <set>
  29. #include <map>
  30. //#define lson i<<1
  31. //#define rson i<<1|1
  32. #define ll long long
  33. #define clr(a,b) memset(a,b,sizeof(a))
  34. #define scanfi(a) scanf("%d",&a)
  35. #define scanfs(a) scanf("%s",a)
  36. #define scanfl(a) scanf("%I64d",&a)
  37. #define scanfd(a) scanf("%lf",&a)
  38. #define key_val ch[ch[root][1]][0]
  39. #define eps 1e-7
  40. #define inf 0x3f3f3f3f3f3f3f3f
  41. using namespace std;
  42. const ll mod = 1e9+7;
  43. const int maxn = 100010;
  44. const double PI = acos(-1.0);
  45.  
  46. template<class T> void read(T&num)
  47. {
  48. char CH;
  49. bool F=false;
  50. for(CH=getchar(); CH<'0'||CH>'9'; F= CH=='-',CH=getchar());
  51. for(num=0; CH>='0'&&CH<='9'; num=num*10+CH-'0',CH=getchar());
  52. F && (num=-num);
  53. }
  54. int stk[70], tp;
  55. template<class T> inline void print(T p)
  56. {
  57. if(!p)
  58. {
  59. puts("0");
  60. return;
  61. }
  62. while(p) stk[++ tp] = p%10, p/=10;
  63. while(tp) putchar(stk[tp--] + '0');
  64. putchar('\n');
  65. }
  66.  
  67. struct Edge
  68. {
  69. int to,next;
  70. };
  71. Edge edge[maxn*2];
  72. int tot,head[maxn];
  73. int in[maxn];
  74. int cnt;
  75. void ini()
  76. {
  77. tot = 0;
  78. cnt = 0;
  79. memset(in,0,sizeof(in));
  80. memset(head,-1,sizeof(head));
  81. }
  82. void add_edge(int u,int v)
  83. {
  84. edge[tot].to = v;
  85. edge[tot].next = head[u];
  86. head[u] = tot++;
  87. }
  88. int dfa[maxn],dfb[maxn],ta[maxn],tb[maxn];
  89. int eda[maxn],edb[maxn];
  90. void dfs(int u,int pre,int flag)
  91. {
  92. if(!flag) dfa[u] = ++ cnt, ta[u] = cnt;
  93. else dfb[u] = ++ cnt, tb[cnt] = ta[u];
  94. for(int i = head[u]; i != -1; i = edge[i].next)
  95. {
  96. int v = edge[i].to;
  97. if(v == pre)continue;
  98. dfs(v,u,flag);
  99. }
  100. if(!flag) eda[u] = cnt;
  101. else edb[u] = cnt;
  102. }
  103.  
  104. int toa;
  105. int lson[maxn * 30],rson[maxn * 30] ;
  106. ll c[maxn * 30];
  107.  
  108. int build(int l,int r)
  109. {
  110. int root = toa ++ ;
  111. c[root] = 0;
  112. if(l != r)
  113. {
  114. int mid = (l+r) >> 1;
  115. build(l,mid);
  116. build(mid+ 1,r);
  117. }
  118. return root ;
  119. }
  120. int n;
  121. int update(int root,int pos,ll val)
  122. {
  123. int newroot = toa ++ ,tmp = newroot;
  124. c[newroot ] = c[root] + val;
  125. int l = 1,r = n;
  126.  
  127. while(l < r)
  128. {
  129. int mid = (l+r) >> 1;
  130. if(pos <= mid)
  131. {
  132. lson[newroot] = toa ++ ,rson[newroot] = rson[root];
  133. newroot = lson[newroot],root = lson[root];
  134. r = mid;
  135. }
  136. else
  137. {
  138. rson[newroot] = toa ++ ,lson[newroot] = lson[root];
  139. newroot = rson[newroot] ,root = rson[root];
  140. l = mid + 1;
  141. }
  142. c[newroot] = c[root] + val;
  143. }
  144. return tmp;
  145. }
  146.  
  147. ll query(int root1,int root2,int la,int ra,int l,int r)
  148. {
  149. if(l >= la && r <= ra)
  150. {
  151. return c[root2] - c[root1];
  152. }
  153. int mid = (l + r) >> 1;
  154. ll ans = 0;
  155. if(la <= mid)
  156. {
  157. ans += query(lson[root1],lson[root2],la,ra,l,mid);
  158. }
  159. if(ra > mid)
  160. {
  161. ans += query(rson[root1],rson[root2],la,ra,mid+1,r);
  162. }
  163. return ans;
  164. }
  165.  
  166. void cal(int flag)
  167. {
  168. int u,v;
  169. ini();
  170. for(int i = 1; i < n; i++)
  171. {
  172. read(u),read(v);
  173. add_edge(u,v);
  174. add_edge(v,u);
  175. in[v] ++ ;
  176. }
  177. for(int i = 1; i <= n;i++)
  178. {
  179. if(!in[i])
  180. {
  181. dfs(i,-1,flag);
  182. break;
  183. }
  184. }
  185. }
  186. int T[maxn];
  187. int main()
  188. {
  189. // freopen("in.txt","r",stdin);
  190. read(n);
  191. toa = 0;
  192. cal(0);
  193. cal(1);
  194. T[0] = build(1,n);
  195. for(int i = 1;i <= n;i++)
  196. {
  197. T[i] = update(T[i-1],tb[i],1);
  198. }
  199. ll ans = 0;
  200. for(int i = 1;i <= n;i++)
  201. {
  202. int l = dfb[i],r = edb[i];
  203. ll t = query(T[l],T[r],dfa[i],eda[i],1,n);
  204. ans += 1LL*t*(t-1)/2;
  205. }
  206. printf("%I64d\n",ans);
  207. return 0;
  208. }

  

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-4 换硬币 2 .设计思路 第一步:定义3个整型变量i,j,k用于循环,定义3个整型变量x,count,total分别用于储存零钱数额,换法个数,硬币数量: 第二步:输 ...

  2. SDVN

    Software Defined Vehicular Networks VANET 车载自组网(VANET)是指在交通环境中车辆之间.车辆与固定接入点之间及车辆与行人之间相互通信组成的开放式移动Ad ...

  3. win10 安装mingw ruby rails

    原文可以参考 https://ruby-china.org/topics/17581 在window10 安装ruby rails https://rubyinstaller.org/download ...

  4. IE浏览器支持响应式网站设计

    目前响应式网站设计比较流行, 下面是摘自百度百科有关响应式设计的定义. 响应式网站设计是一种网络页面设计布局,其理念是:集中创建页面的图片排版大小,可以智能地根据用户行为以及使用的设备环境进行相对应的 ...

  5. JAVA_SE基础——70.Math类

    package cn.itcast.other; /*  Math 数学类, 主要是提供了很多的数学公式.    abs(double a)  获取绝对值  ceil(double a)  向上取整 ...

  6. TFTP通信原理

    TFTP的通信流程 TFTP共定义了五种类型的包格式,格式的区分由包数据前两个字节的Opcode字段区分,分别是: · l 读文件请求包:Read request,简写为RRQ,对应Opcode字段值 ...

  7. dede使用心得

    Question one: 最近做了一些视频教程传到优酷网站上,但我想引入这些视频教程到我的网站,在发表时我发现织梦CMS自带的编辑器又不直接支持优酷等视频网站的引用.所以为了方便教程的发布,特意在网 ...

  8. app测试中遇到问题总结

    工作总结: 1 这两天由于工作,需要进行抓包,使用了Charles,fidder,发现一个坑点: charles没有抓到返回值的时候,默认是不在列表显示请求信息的,能不能设置,我就不知道了,但是可以在 ...

  9. jenkins简单安装及配置(Windows环境)

    jenkins是一款跨平台的持续集成和持续交付.基于Java开发的开源软件,提供任务构建,持续集成监控的功能,可以使开发测试人员更方便的构建软件项目,提高工作效率. Windows平台下,一般安装方法 ...

  10. tomcat-theory

    (一) java类:applet,servlet,jsp JSP:.jsp-->.java-->(JVM).classJDK:javac,.java-->.classweb:Serv ...